Files
mercury/compiler/layout_out.m
Zoltan Somogyi 0d6c3c9fdf Satisfy a request by Peter Ross: give mdb users the ability to specify
Estimated hours taken: 8
Branches: main

Satisfy a request by Peter Ross: give mdb users the ability to specify
exactly which events inside a procedure they want to put breakpoints on.
Amongst other things, this can make checking postconditions easier:
you can now put a conditional breakpoint on only the exit event.

runtime/mercury_stack_layout.h:
	Add to the exec trace part of proc layouts fields describing an array
	of the label layouts describing the events of the procedure. This is
	the most direct way to implement the new functionality. (In theory,
	we could search the data structures that map file names and line
	numbers to label layouts, but that would be complex, inefficient,
	and *error prone*.)

	To make room for the new fields, and to prepare for making the
	procedure body available to the deep profiler as well (which could
	use it to map execution frequencies of calls back to their location
	in the procedure body, and thus to things like the frequencies with
	which various switch arms are selected), move the procedure body
	of the execution-trace-specific part of the proc layout, and to
	where the deep profiler could in the future also get at it.

runtime/mercury_goto.h:
	Add macros for declaring more than one label layout structure at a
	time.

compiler/layout.m:
	Implement the changes in mercury_stack_layout.h in the compiler's
	data structures as well.

compiler/stack_layout.m:
	Conform to the changes in mercury_stack_layout.h.

	Turn some tuples into named types.

compiler/layout_out.m:
	Conform to the changes in mercury_stack_layout.h.

	Add a mechanism to declare the label layouts in the new array before
	referring to them, by generalizing some existing code. Make this code
	require that the label layouts we refer to via the macros in
	mercury_goto.h match the declarations generated by those macros,
	i.e. that they have information about variables (if debugging is
	enabled, they will).

compiler/opt_debug.m:
	Conform to the change to layout.m.

compiler/prog_rep.m:
	Make a predicate name more expressive.

trace/mercury_trace_cmd_breakpoint.c:
	Implement the new way of using the "break" command, which is
	to add a port name after the procedure specification.

	Register procedures at the start of the function implementing
	the "break" command, instead of "on demand", since all alternatives
	eventually do demand it.

	Write ambiguity reports wholly to mdb's stdout, instead of partially to
	stderr and partially to stdout.

trace/mercury_trace_spy.c:
	Print the port and the goal path for breakpoints on specific events.

	Make the invocation conditions left-aligned, not right-aligned.

doc/user_guide.texi:
	Document the new way of using the "break" command.

NEWS:
	Announce the new capability.

tests/queens.{inp,exp,exp2}:
	Add tests of the new capability.

tests/breakpoints.{exp,exp}:
tests/lval_desc_array.{exp,exp2}:
	Expect the new alignment of invocation conditions.
2007-06-12 06:06:35 +00:00

2214 lines
86 KiB
Mathematica

%-----------------------------------------------------------------------------%
% vim: ft=mercury ts=4 sw=4 et
%-----------------------------------------------------------------------------%
% Copyright (C) 2001-2007 The University of Melbourne.
% This file may only be copied under the terms of the GNU General
% Public License - see the file COPYING in the Mercury distribution.
%-----------------------------------------------------------------------------%
%
% File: layout_out.m.
% Author: zs.
%
% This structure converts layout structures from the representation used
% within the compiler to the representation used by the runtime system.
% The types of the inputs are defined in layout.m. The types of the outputs
% are defined in runtime/mercury_stack_layout.h, where the documentation
% of the semantics of the various kinds of layout structures can also be found.
%
% This module should be, but as yet isn't, independent of whether we are
% compiling to LLDS or MLDS.
%
%-----------------------------------------------------------------------------%
:- module ll_backend.layout_out.
:- interface.
:- import_module ll_backend.layout.
:- import_module ll_backend.llds.
:- import_module ll_backend.llds_out.
:- import_module mdbcomp.prim_data.
:- import_module bool.
:- import_module io.
%-----------------------------------------------------------------------------%
% Given a Mercury representation of a layout structure, output its
% definition in the appropriate C global variable.
%
:- pred output_layout_data_defn(layout_data::in, decl_set::in, decl_set::out,
io::di, io::uo) is det.
% Given the name of a layout structure, output the declaration
% of the C global variable which will hold it.
%
:- pred output_layout_name_decl(layout_name::in, io::di, io::uo) is det.
% Given the name of a layout structure, output the declaration of the C
% global variable which will hold it, if it has not already been declared.
:- pred output_maybe_layout_name_decl(layout_name::in,
decl_set::in, decl_set::out, io::di, io::uo) is det.
% Given a Mercury representation of a layout structure, output the
% declaration of the C global variable which will hold it, if it has
% not already been declared.
%
:- pred output_maybe_layout_data_decl(layout_data::in,
decl_set::in, decl_set::out, io::di, io::uo) is det.
% Given a reference to a layout structure, output the storage class
% (e.g. static), type and name of the global variable that will
% hold it. The bool says whether the output is part of the definition of
% that variable (this influences e.g. whether we output "extern" or not).
%
:- pred output_layout_name_storage_type_name(layout_name::in, bool::in,
io::di, io::uo) is det.
% Given a reference to a layout structure, output the name of the
% global variable that will hold it.
%
:- pred output_layout_name(layout_name::in, io::di, io::uo) is det.
% Given a reference to a layout structure, return a bool that is true
% iff the layout structure contains code addresses.
%
:- func layout_name_would_include_code_addr(layout_name) = bool.
% Given a label, return a string giving the name of the global variable
% containing the label layout structure that would be associated with it.
% Make_label_layout_name does not guarantee that the label *has* an
% associated label layout structure.
%
:- func make_label_layout_name(label) = string.
% For a given procedure label, return whether the procedure is
% user-defined or part of a compiler-generated unify, compare or index
% predicate.
%
:- func proc_label_user_or_uci(proc_label) = proc_layout_user_or_uci.
% Output a value of C type MR_PredFunc corrresponding to the argument.
%
:- pred output_pred_or_func(pred_or_func::in, io::di, io::uo) is det.
% Return the name of the given port, as in the enum MR_Trace_Port
% in runtime/mercury_stack_layout.h.
%
:- func trace_port_to_string(trace_port) = string.
%-----------------------------------------------------------------------------%
%-----------------------------------------------------------------------------%
:- implementation.
:- import_module backend_libs.c_util.
:- import_module backend_libs.name_mangle.
:- import_module backend_libs.proc_label.
:- import_module hlds.hlds_goal.
:- import_module hlds.hlds_pred.
:- import_module hlds.hlds_rtti.
:- import_module hlds.special_pred.
:- import_module libs.compiler_util.
:- import_module libs.trace_params.
:- import_module mdbcomp.program_representation.
:- import_module parse_tree.mercury_to_mercury.
:- import_module parse_tree.prog_data.
:- import_module parse_tree.prog_foreign.
:- import_module assoc_list.
:- import_module char.
:- import_module int.
:- import_module list.
:- import_module map.
:- import_module maybe.
:- import_module pair.
:- import_module string.
:- import_module varset.
%-----------------------------------------------------------------------------%
output_layout_data_defn(Data, !DeclSet, !IO) :-
(
Data = label_layout_data(ProcLabel, LabelNum, ProcLayoutAddr,
MaybePort, MaybeIsHidden, LabelNumber, MaybeGoalPath,
MaybeUserData, MaybeVarInfo),
output_label_layout_data_defn(ProcLabel, LabelNum, ProcLayoutAddr,
MaybePort, MaybeIsHidden, LabelNumber, MaybeGoalPath,
MaybeUserData, MaybeVarInfo, !DeclSet, !IO)
;
Data = proc_layout_data(ProcLabel, Traversal, MaybeRest),
output_proc_layout_data_defn(ProcLabel, Traversal, MaybeRest,
!DeclSet, !IO)
;
Data = closure_proc_id_data(CallerProcLabel, SeqNo, ProcLabel,
ModuleName, FileName, LineNumber, PredOrigin, GoalPath),
output_closure_proc_id_data_defn(CallerProcLabel, SeqNo, ProcLabel,
ModuleName, FileName, LineNumber, PredOrigin, GoalPath,
!DeclSet, !IO)
;
Data = module_layout_data(ModuleName, StringTableSize,
StringTable, ProcLayoutNames, FileLayouts, TraceLevel,
SuppressedEvents, NumLabels, MaybeEventSet),
output_module_layout_data_defn(ModuleName, StringTableSize,
StringTable, ProcLayoutNames, FileLayouts, TraceLevel,
SuppressedEvents, NumLabels, MaybeEventSet, !DeclSet, !IO)
;
Data = table_io_decl_data(RttiProcLabel, Kind, NumPTIs,
PTIVectorRval, TypeParamsRval),
output_table_io_decl(RttiProcLabel, Kind, NumPTIs,
PTIVectorRval, TypeParamsRval, !DeclSet, !IO)
).
%-----------------------------------------------------------------------------%
output_layout_name_decl(LayoutName, !IO) :-
output_layout_name_storage_type_name(LayoutName, no, !IO),
io.write_string(";\n", !IO).
output_maybe_layout_name_decl(LayoutName, !DeclSet, !IO) :-
( decl_set_is_member(decl_data_addr(layout_addr(LayoutName)), !.DeclSet) ->
true
;
output_layout_name_decl(LayoutName, !IO),
decl_set_insert(decl_data_addr(layout_addr(LayoutName)), !DeclSet)
).
output_maybe_layout_data_decl(LayoutData, !DeclSet, !IO) :-
extract_layout_name(LayoutData, LayoutName),
output_maybe_layout_name_decl(LayoutName, !DeclSet, !IO).
:- pred extract_layout_name(layout_data::in, layout_name::out) is det.
extract_layout_name(Data, LayoutName) :-
(
Data = label_layout_data(ProcLabel, LabelNum, _, _, _, _, _, _,
MaybeVarInfo),
(
MaybeVarInfo = yes(_),
LabelVars = label_has_var_info
;
MaybeVarInfo = no,
LabelVars = label_has_no_var_info
),
LayoutName = label_layout(ProcLabel, LabelNum, LabelVars)
;
Data = proc_layout_data(RttiProcLabel, _, MaybeRest),
ProcLabel = make_proc_label_from_rtti(RttiProcLabel),
Kind = maybe_proc_layout_and_more_kind(MaybeRest, ProcLabel),
LayoutName = proc_layout(RttiProcLabel, Kind)
;
Data = closure_proc_id_data(CallerProcLabel, SeqNo, ClosureProcLabel,
_, _, _, _, _),
LayoutName = closure_proc_id(CallerProcLabel, SeqNo, ClosureProcLabel)
;
Data = module_layout_data(ModuleName, _, _, _, _, _, _, _, _),
LayoutName = module_layout(ModuleName)
;
Data = table_io_decl_data(RttiProcLabel, _, _, _, _),
LayoutName = table_io_decl(RttiProcLabel)
).
:- pred output_layout_decl(layout_name::in, decl_set::in, decl_set::out,
io::di, io::uo) is det.
output_layout_decl(LayoutName, !DeclSet, !IO) :-
( decl_set_is_member(decl_data_addr(layout_addr(LayoutName)), !.DeclSet) ->
true
;
output_layout_name_storage_type_name(LayoutName, no, !IO),
io.write_string(";\n", !IO),
decl_set_insert(decl_data_addr(layout_addr(LayoutName)), !DeclSet)
).
% This code should be kept in sync with output_layout_name/3 below.
make_label_layout_name(Label) = Name :-
% We can't omit the mercury_ prefix on LabelName, even though the
% mercury_data_prefix duplicates it, because there is no simple way
% to make the MR_init_label_sl macro delete that prefix from the
% label's name to get the name of its layout structure.
LabelName = label_to_c_string(Label, yes),
string.append_list([
mercury_data_prefix,
"_label_layout__",
LabelName
], Name).
output_layout_name(Data, !IO) :-
(
Data = label_layout(ProcLabel, LabelNum, _),
% This code should be kept in sync with make_label_layout_name/1 above.
io.write_string(mercury_data_prefix, !IO),
io.write_string("_label_layout__", !IO),
io.write_string(
label_to_c_string(internal_label(LabelNum, ProcLabel), yes), !IO)
;
Data = user_event_layout(ProcLabel, LabelNum),
io.write_string(mercury_data_prefix, !IO),
io.write_string("_user_event_layout__", !IO),
io.write_string(
label_to_c_string(internal_label(LabelNum, ProcLabel), yes), !IO)
;
Data = user_event_attr_var_nums(ProcLabel, LabelNum),
io.write_string(mercury_data_prefix, !IO),
io.write_string("_user_event_attr_var_nums__", !IO),
io.write_string(
label_to_c_string(internal_label(LabelNum, ProcLabel), yes), !IO)
;
Data = proc_layout(RttiProcLabel, _),
io.write_string(mercury_data_prefix, !IO),
io.write_string("_proc_layout__", !IO),
% We can't omit the mercury_ prefix on ProcLabel, even though the
% mercury_data_prefix duplicates it, because there is no simply way
% to make the MR_init_entryl_sl macro delete that prefix from the
% entry label's name to get the name of its layout structure.
output_proc_label(make_proc_label_from_rtti(RttiProcLabel), !IO)
;
Data = proc_layout_exec_trace(RttiProcLabel),
io.write_string(mercury_data_prefix, !IO),
io.write_string("_proc_layout_exec_trace__", !IO),
output_proc_label_no_prefix(make_proc_label_from_rtti(RttiProcLabel),
!IO)
;
Data = proc_layout_label_layouts(RttiProcLabel),
io.write_string(mercury_data_prefix, !IO),
io.write_string("_proc_label_layouts__", !IO),
output_proc_label_no_prefix(make_proc_label_from_rtti(RttiProcLabel),
!IO)
;
Data = proc_layout_head_var_nums(RttiProcLabel),
io.write_string(mercury_data_prefix, !IO),
io.write_string("_head_var_nums__", !IO),
output_proc_label_no_prefix(make_proc_label_from_rtti(RttiProcLabel),
!IO)
;
Data = proc_layout_var_names(RttiProcLabel),
io.write_string(mercury_data_prefix, !IO),
io.write_string("_var_names__", !IO),
output_proc_label_no_prefix(make_proc_label_from_rtti(RttiProcLabel),
!IO)
;
Data = proc_layout_body_bytecode(RttiProcLabel),
io.write_string(mercury_data_prefix, !IO),
io.write_string("_body_bytecode__", !IO),
output_proc_label_no_prefix(make_proc_label_from_rtti(RttiProcLabel),
!IO)
;
Data = closure_proc_id(CallerProcLabel, SeqNo, _),
io.write_string(mercury_data_prefix, !IO),
io.write_string("_closure_layout__", !IO),
output_proc_label_no_prefix(CallerProcLabel, !IO),
io.write_string("_", !IO),
io.write_int(SeqNo, !IO)
;
Data = file_layout(ModuleName, FileNum),
io.write_string(mercury_data_prefix, !IO),
io.write_string("_file_layout__", !IO),
ModuleNameStr = sym_name_mangle(ModuleName),
io.write_string(ModuleNameStr, !IO),
io.write_string("_", !IO),
io.write_int(FileNum, !IO)
;
Data = file_layout_line_number_vector(ModuleName, FileNum),
io.write_string(mercury_data_prefix, !IO),
io.write_string("_file_lines__", !IO),
ModuleNameStr = sym_name_mangle(ModuleName),
io.write_string(ModuleNameStr, !IO),
io.write_string("_", !IO),
io.write_int(FileNum, !IO)
;
Data = file_layout_label_layout_vector(ModuleName, FileNum),
io.write_string(mercury_data_prefix, !IO),
io.write_string("_file_label_layouts__", !IO),
ModuleNameStr = sym_name_mangle(ModuleName),
io.write_string(ModuleNameStr, !IO),
io.write_string("_", !IO),
io.write_int(FileNum, !IO)
;
Data = module_layout_string_table(ModuleName),
io.write_string(mercury_data_prefix, !IO),
io.write_string("_module_strings__", !IO),
ModuleNameStr = sym_name_mangle(ModuleName),
io.write_string(ModuleNameStr, !IO)
;
Data = module_layout_file_vector(ModuleName),
io.write_string(mercury_data_prefix, !IO),
io.write_string("_module_files__", !IO),
ModuleNameStr = sym_name_mangle(ModuleName),
io.write_string(ModuleNameStr, !IO)
;
Data = module_layout_proc_vector(ModuleName),
io.write_string(mercury_data_prefix, !IO),
io.write_string("_module_procs__", !IO),
ModuleNameStr = sym_name_mangle(ModuleName),
io.write_string(ModuleNameStr, !IO)
;
Data = module_layout_label_exec_count(ModuleName, _),
io.write_string(mercury_data_prefix, !IO),
io.write_string("_module_label_exec_counts__", !IO),
ModuleNameStr = sym_name_mangle(ModuleName),
io.write_string(ModuleNameStr, !IO)
;
Data = module_layout_event_set_desc(ModuleName),
io.write_string(mercury_data_prefix, !IO),
io.write_string("_module_layout_event_set_desc__", !IO),
ModuleNameStr = sym_name_mangle(ModuleName),
io.write_string(ModuleNameStr, !IO)
;
Data = module_layout_event_arg_names(ModuleName, EventNumber),
io.write_string(mercury_data_prefix, !IO),
io.write_string("_module_layout_event_arg_names__", !IO),
ModuleNameStr = sym_name_mangle(ModuleName),
io.write_string(ModuleNameStr, !IO),
io.write_string("_", !IO),
io.write_int(EventNumber, !IO)
;
Data = module_layout_event_synth_attrs(ModuleName, EventNumber),
io.write_string(mercury_data_prefix, !IO),
io.write_string("_module_layout_event_synth_attrs__", !IO),
ModuleNameStr = sym_name_mangle(ModuleName),
io.write_string(ModuleNameStr, !IO),
io.write_string("_", !IO),
io.write_int(EventNumber, !IO)
;
Data = module_layout_event_synth_attr_args(ModuleName,
EventNumber, SynthCallArgNumber),
io.write_string(mercury_data_prefix, !IO),
io.write_string("_module_layout_event_synth_attr_args__", !IO),
ModuleNameStr = sym_name_mangle(ModuleName),
io.write_string(ModuleNameStr, !IO),
io.write_string("_", !IO),
io.write_int(EventNumber, !IO),
io.write_string("_", !IO),
io.write_int(SynthCallArgNumber, !IO)
;
Data = module_layout_event_synth_attr_order(ModuleName,
EventNumber, SynthCallArgNumber),
io.write_string(mercury_data_prefix, !IO),
io.write_string("_module_layout_event_synth_attr_order__", !IO),
ModuleNameStr = sym_name_mangle(ModuleName),
io.write_string(ModuleNameStr, !IO),
io.write_string("_", !IO),
io.write_int(EventNumber, !IO),
io.write_string("_", !IO),
io.write_int(SynthCallArgNumber, !IO)
;
Data = module_layout_event_synth_order(ModuleName, EventNumber),
io.write_string(mercury_data_prefix, !IO),
io.write_string("_module_layout_event_synth_order__", !IO),
ModuleNameStr = sym_name_mangle(ModuleName),
io.write_string(ModuleNameStr, !IO),
io.write_string("_", !IO),
io.write_int(EventNumber, !IO)
;
Data = module_layout_event_specs(ModuleName),
io.write_string(mercury_data_prefix, !IO),
io.write_string("_module_layout_event_specs__", !IO),
ModuleNameStr = sym_name_mangle(ModuleName),
io.write_string(ModuleNameStr, !IO)
;
Data = module_layout(ModuleName),
io.write_string(mercury_data_prefix, !IO),
io.write_string("_module_layout__", !IO),
ModuleNameStr = sym_name_mangle(ModuleName),
io.write_string(ModuleNameStr, !IO)
;
Data = proc_static(RttiProcLabel),
io.write_string(mercury_data_prefix, !IO),
io.write_string("_proc_static__", !IO),
ProcLabel = make_proc_label_from_rtti(RttiProcLabel),
output_proc_label_no_prefix(ProcLabel, !IO)
;
Data = proc_static_call_sites(RttiProcLabel),
io.write_string(mercury_data_prefix, !IO),
io.write_string("_proc_static_call_sites__", !IO),
ProcLabel = make_proc_label_from_rtti(RttiProcLabel),
output_proc_label_no_prefix(ProcLabel, !IO)
;
Data = table_io_decl(RttiProcLabel),
io.write_string(mercury_data_prefix, !IO),
io.write_string("_table_io_decl__", !IO),
ProcLabel = make_proc_label_from_rtti(RttiProcLabel),
output_proc_label_no_prefix(ProcLabel, !IO)
).
output_layout_name_storage_type_name(Name, BeingDefined, !IO) :-
(
Name = label_layout(_ProcLabel, _LabelNum, LabelVars),
io.write_string("static const ", !IO),
io.write_string(label_vars_to_type(LabelVars), !IO),
io.write_string(" ", !IO),
output_layout_name(Name, !IO)
;
Name = user_event_layout(_ProcLabel, _LabelNum),
io.write_string("static const struct MR_UserEvent_Struct ", !IO),
output_layout_name(Name, !IO)
;
Name = user_event_attr_var_nums(_ProcLabel, _LabelNum),
io.write_string("static const MR_HLDSVarNum ", !IO),
output_layout_name(Name, !IO),
io.write_string("[]", !IO)
;
Name = proc_layout(ProcLabel, Kind),
ProcIsImported = ProcLabel ^ proc_is_imported,
ProcIsExported = ProcLabel ^ proc_is_exported,
(
ProcIsImported = no,
ProcIsExported = no
->
io.write_string("static ", !IO)
;
(
BeingDefined = yes
;
BeingDefined = no,
io.write_string("extern ", !IO)
)
),
io.write_string("const ", !IO),
io.write_string(proc_layout_kind_to_type(Kind), !IO),
io.write_string(" ", !IO),
output_layout_name(Name, !IO)
;
Name = proc_layout_exec_trace(_ProcLabel),
io.write_string("static MR_STATIC_CODE_CONST MR_ExecTrace\n\t", !IO),
output_layout_name(Name, !IO)
;
Name = proc_layout_label_layouts(_ProcLabel),
io.write_string("static const MR_LabelLayout *", !IO),
output_layout_name(Name, !IO),
io.write_string("[]", !IO)
;
Name = proc_layout_head_var_nums(_ProcLabel),
io.write_string("static const ", !IO),
io.write_string("MR_uint_least16_t ", !IO),
output_layout_name(Name, !IO),
io.write_string("[]", !IO)
;
Name = proc_layout_var_names(_ProcLabel),
io.write_string("static const ", !IO),
io.write_string("MR_uint_least32_t ", !IO),
output_layout_name(Name, !IO),
io.write_string("[]", !IO)
;
Name = proc_layout_body_bytecode(_ProcLabel),
io.write_string("static const ", !IO),
io.write_string("MR_uint_least8_t ", !IO),
output_layout_name(Name, !IO),
io.write_string("[]", !IO)
;
Name = closure_proc_id(_CallerProcLabel, _SeqNo, ClosureProcLabel),
io.write_string("static const ", !IO),
(
ClosureProcLabel = ordinary_proc_label(_, _, _, _, _, _),
io.write_string("MR_UserClosureId\n", !IO)
;
ClosureProcLabel = special_proc_label(_, _, _, _, _, _),
io.write_string("MR_UCIClosureId\n", !IO)
),
output_layout_name(Name, !IO)
;
Name = file_layout(_ModuleName, _FileNum),
io.write_string("static const MR_ModuleFileLayout ", !IO),
output_layout_name(Name, !IO)
;
Name = file_layout_line_number_vector(_ModuleName, _FileNum),
io.write_string("static const MR_int_least16_t ", !IO),
output_layout_name(Name, !IO),
io.write_string("[]", !IO)
;
Name = file_layout_label_layout_vector(_ModuleName, _FileNum),
io.write_string("static const MR_LabelLayout *", !IO),
output_layout_name(Name, !IO),
io.write_string("[]", !IO)
;
Name = module_layout_string_table(_ModuleName),
io.write_string("static const char ", !IO),
output_layout_name(Name, !IO),
io.write_string("[]", !IO)
;
Name = module_layout_file_vector(_ModuleName),
io.write_string("static const MR_ModuleFileLayout *", !IO),
output_layout_name(Name, !IO),
io.write_string("[]", !IO)
;
Name = module_layout_label_exec_count(_ModuleName, NumElements),
io.write_string("static MR_Unsigned ", !IO),
output_layout_name(Name, !IO),
io.write_string("[", !IO),
io.write_int(NumElements, !IO),
io.write_string("]", !IO)
;
Name = module_layout_proc_vector(_ModuleName),
io.write_string("static const MR_ProcLayout *", !IO),
output_layout_name(Name, !IO),
io.write_string("[]", !IO)
;
Name = module_layout_event_set_desc(_ModuleName),
io.write_string("static const char ", !IO),
output_layout_name(Name, !IO),
io.write_string("[]", !IO)
;
Name = module_layout_event_arg_names(_ModuleName, _EventNumber),
io.write_string("static const char * ", !IO),
output_layout_name(Name, !IO),
io.write_string("[]", !IO)
;
Name = module_layout_event_synth_attrs(_ModuleName, _EventNumber),
io.write_string("static MR_SynthAttr ", !IO),
output_layout_name(Name, !IO),
io.write_string("[]", !IO)
;
Name = module_layout_event_synth_attr_args(_ModuleName,
_EventNumber, _SynthCallArgNumber),
io.write_string("static MR_uint_least16_t ", !IO),
output_layout_name(Name, !IO),
io.write_string("[]", !IO)
;
Name = module_layout_event_synth_attr_order(_ModuleName,
_EventNumber, _SynthCallArgNumber),
io.write_string("static MR_uint_least16_t ", !IO),
output_layout_name(Name, !IO),
io.write_string("[]", !IO)
;
Name = module_layout_event_synth_order(_ModuleName, _EventNumber),
io.write_string("static MR_int_least16_t ", !IO),
output_layout_name(Name, !IO),
io.write_string("[]", !IO)
;
Name = module_layout_event_specs(_ModuleName),
io.write_string("static MR_UserEventSpec ", !IO),
output_layout_name(Name, !IO),
io.write_string("[]", !IO)
;
Name = module_layout(_ModuleName),
io.write_string("static const MR_ModuleLayout ", !IO),
output_layout_name(Name, !IO)
;
Name = proc_static(_RttiProcLabel),
io.write_string("static MR_ProcStatic ", !IO),
output_layout_name(Name, !IO)
;
Name = proc_static_call_sites(_RttiProcLabel),
io.write_string("static const MR_CallSiteStatic ", !IO),
output_layout_name(Name, !IO),
io.write_string("[]", !IO)
;
Name = table_io_decl(_RttiProcLabel),
io.write_string("static const MR_TableIoDecl ", !IO),
output_layout_name(Name, !IO)
).
layout_name_would_include_code_addr(label_layout(_, _, _)) = no.
layout_name_would_include_code_addr(user_event_layout(_, _)) = no.
layout_name_would_include_code_addr(user_event_attr_var_nums(_, _)) = no.
layout_name_would_include_code_addr(proc_layout(_, _)) = no.
layout_name_would_include_code_addr(proc_layout_exec_trace(_)) = yes.
layout_name_would_include_code_addr(proc_layout_label_layouts(_)) = no.
layout_name_would_include_code_addr(proc_layout_head_var_nums(_)) = no.
layout_name_would_include_code_addr(proc_layout_var_names(_)) = no.
layout_name_would_include_code_addr(proc_layout_body_bytecode(_)) = no.
layout_name_would_include_code_addr(closure_proc_id(_, _, _)) = no.
layout_name_would_include_code_addr(file_layout(_, _)) = no.
layout_name_would_include_code_addr(file_layout_line_number_vector(_, _)) = no.
layout_name_would_include_code_addr(file_layout_label_layout_vector(_, _))
= no.
layout_name_would_include_code_addr(module_layout_string_table(_)) = no.
layout_name_would_include_code_addr(module_layout_file_vector(_)) = no.
layout_name_would_include_code_addr(module_layout_proc_vector(_)) = no.
layout_name_would_include_code_addr(module_layout_label_exec_count(_, _)) = no.
layout_name_would_include_code_addr(module_layout_event_set_desc(_)) = no.
layout_name_would_include_code_addr(module_layout_event_arg_names(_, _)) = no.
layout_name_would_include_code_addr(module_layout_event_synth_attrs(_, _))
= no.
layout_name_would_include_code_addr(
module_layout_event_synth_attr_args(_, _, _)) = no.
layout_name_would_include_code_addr(
module_layout_event_synth_attr_order(_, _, _)) = no.
layout_name_would_include_code_addr(module_layout_event_synth_order(_, _))
= no.
layout_name_would_include_code_addr(module_layout_event_specs(_)) = no.
layout_name_would_include_code_addr(module_layout(_)) = no.
layout_name_would_include_code_addr(proc_static(_)) = no.
layout_name_would_include_code_addr(proc_static_call_sites(_)) = no.
layout_name_would_include_code_addr(table_io_decl(_)) = no.
:- func label_vars_to_type(label_vars) = string.
label_vars_to_type(label_has_var_info) = "MR_LabelLayout".
label_vars_to_type(label_has_no_var_info) = "MR_LabelLayoutNoVarInfo".
:- func proc_layout_kind_to_type(proc_layout_kind) = string.
proc_layout_kind_to_type(proc_layout_traversal) = "MR_ProcLayout_Traversal".
proc_layout_kind_to_type(proc_layout_proc_id(user)) = "MR_ProcLayoutUser".
proc_layout_kind_to_type(proc_layout_proc_id(uci)) = "MR_ProcLayoutUCI".
%-----------------------------------------------------------------------------%
:- type rval_or_numpair_or_none
---> kind_rval(rval)
; kind_num_pair(type_num, int)
; kind_none.
:- pred output_rval_or_numpair_or_none(rval_or_numpair_or_none::in,
io::di, io::uo) is det.
output_rval_or_numpair_or_none(kind_rval(Rval), !IO) :-
io.write_string(", ", !IO),
output_rval_as_addr(Rval, !IO).
output_rval_or_numpair_or_none(kind_num_pair(type_num(Num1), Num2), !IO) :-
io.write_string(", ", !IO),
io.write_int(Num1, !IO),
io.write_string(", ", !IO),
io.write_int(Num2, !IO).
output_rval_or_numpair_or_none(kind_none, !IO).
:- pred output_label_layout_data_defn(proc_label::in, int::in, layout_name::in,
maybe(trace_port)::in, maybe(bool)::in, int::in, maybe(int)::in,
maybe(user_event_data)::in, maybe(label_var_info)::in,
decl_set::in, decl_set::out, io::di, io::uo) is det.
output_label_layout_data_defn(ProcLabel, LabelNum, ProcLayoutAddr, MaybePort,
MaybeIsHidden, LabelNumberInModule, MaybeGoalPath, MaybeUserData,
MaybeVarInfo, !DeclSet, !IO) :-
output_layout_decl(ProcLayoutAddr, !DeclSet, !IO),
(
MaybeUserData = no,
UserChars = ""
;
MaybeUserData = yes(UserData),
UserChars = "_U",
UserData = user_event_data(UserEventNumber, UserLocnsRval,
UserAttrMaybeVarNums),
AttrVarNumsLayoutName = user_event_attr_var_nums(ProcLabel, LabelNum),
AttrVarNumsDataAddr = layout_addr(AttrVarNumsLayoutName),
decl_set_insert(decl_data_addr(AttrVarNumsDataAddr), !DeclSet),
output_layout_name_storage_type_name(AttrVarNumsLayoutName, no, !IO),
io.write_string(" = {\n", !IO),
io.write_list(UserAttrMaybeVarNums, ", ", output_maybe_var_num, !IO),
io.write_string("\n};\n\n", !IO),
UserLayoutName = user_event_layout(ProcLabel, LabelNum),
UserDataAddr = layout_addr(UserLayoutName),
decl_set_insert(decl_data_addr(UserDataAddr), !DeclSet),
output_layout_name_storage_type_name(UserLayoutName, no, !IO),
io.write_string(" = {\n", !IO),
io.write_int(UserEventNumber, !IO),
io.write_string(",\n(MR_LongLval *) ", !IO),
output_rval_as_addr(UserLocnsRval, !IO),
io.write_string(",\n", !IO),
output_layout_name(AttrVarNumsLayoutName, !IO),
io.write_string("\n};\n\n", !IO)
),
(
MaybeIsHidden = yes(yes),
HiddenChars = "T"
;
MaybeIsHidden = yes(no),
HiddenChars = ""
;
MaybeIsHidden = no,
% The value of the hidden field shouldn't matter here.
HiddenChars = ""
),
(
MaybeVarInfo = yes(VarInfo0),
VarInfo0 = label_var_info(EncodedVarCount1, LocnsTypes0, VarNums0,
TypeParams0),
output_rval_decls(LocnsTypes0, !DeclSet, !IO),
output_rval_decls(VarNums0, !DeclSet, !IO),
output_rval_decls(TypeParams0, !DeclSet, !IO),
LabelVars = label_has_var_info,
(
LocnsTypes0 = const(llconst_data_addr(LTDataAddr, no)),
LTDataAddr = data_addr(_, scalar_common_ref(LTTypeNum, LTCellNum)),
VarNums0 = const(llconst_data_addr(VNDataAddr, no)),
VNDataAddr = data_addr(_, scalar_common_ref(VNTypeNum, VNCellNum))
->
(
TypeParams0 = const(llconst_data_addr(TPDataAddr, no)),
TPDataAddr = data_addr(_,
scalar_common_ref(TPTypeNum, TPCellNum))
->
CommonChars = "XCCC",
LocnsTypes1 = kind_num_pair(LTTypeNum, LTCellNum),
VarNums1 = kind_num_pair(VNTypeNum, VNCellNum),
TypeParams1 = kind_num_pair(TPTypeNum, TPCellNum)
;
TypeParams0 = const(llconst_int(0))
->
CommonChars = "XCC0",
LocnsTypes1 = kind_num_pair(LTTypeNum, LTCellNum),
VarNums1 = kind_num_pair(VNTypeNum, VNCellNum),
TypeParams1 = kind_none
;
CommonChars = "",
LocnsTypes1 = kind_rval(LocnsTypes0),
VarNums1 = kind_rval(VarNums0),
TypeParams1 = kind_rval(TypeParams0)
)
;
CommonChars = "",
LocnsTypes1 = kind_rval(LocnsTypes0),
VarNums1 = kind_rval(VarNums0),
TypeParams1 = kind_rval(TypeParams0)
),
Macro0 = "MR_DEF_LL" ++ HiddenChars ++ CommonChars,
MaybeVarInfoTuple = yes({EncodedVarCount1, LocnsTypes1, VarNums1,
TypeParams1})
;
MaybeVarInfo = no,
LabelVars = label_has_no_var_info,
Macro0 = "MR_DEF_LLNVI" ++ HiddenChars,
MaybeVarInfoTuple = no
),
Macro = Macro0 ++ UserChars,
LayoutName = label_layout(ProcLabel, LabelNum, LabelVars),
io.write_string("\n", !IO),
io.write_string(Macro, !IO),
io.write_string("(", !IO),
output_proc_label_no_prefix(ProcLabel, !IO),
io.write_string(",\n", !IO),
io.write_int(LabelNum, !IO),
io.write_string(", ", !IO),
(
MaybePort = yes(Port),
io.write_string(trace_port_to_string(Port), !IO)
;
MaybePort = no,
io.write_string("NONE", !IO)
),
io.write_string(", ", !IO),
io.write_int(LabelNumberInModule, !IO),
io.write_string(", ", !IO),
(
MaybeGoalPath = yes(GoalPath),
io.write_int(GoalPath, !IO)
;
MaybeGoalPath = no,
io.write_string("0", !IO)
),
(
MaybeVarInfoTuple = yes({EncodedVarCount,
LocnsTypes, VarNums, TypeParams}),
io.write_string(", ", !IO),
io.write_int(EncodedVarCount, !IO),
output_rval_or_numpair_or_none(LocnsTypes, !IO),
output_rval_or_numpair_or_none(VarNums, !IO),
output_rval_or_numpair_or_none(TypeParams, !IO)
;
MaybeVarInfoTuple = no
),
io.write_string(");\n", !IO),
decl_set_insert(decl_data_addr(layout_addr(LayoutName)), !DeclSet).
:- pred output_maybe_var_num(maybe(int)::in, io::di, io::uo) is det.
output_maybe_var_num(no, !IO) :-
% Zero means not a variable, which is what we want.
io.write_int(0, !IO).
output_maybe_var_num(yes(VarNum), !IO) :-
io.write_int(VarNum, !IO).
% Output the rval in a context in which it is immediately cast to an
% address.
%
:- pred output_rval_as_addr(rval::in, io::di, io::uo) is det.
output_rval_as_addr(Rval, !IO) :-
( Rval = const(llconst_int(0)) ->
io.write_string(" 0", !IO)
; Rval = const(llconst_data_addr(DataAddr, no)) ->
( DataAddr = data_addr(_, scalar_common_ref(_TypeNum, _CellNum)) ->
output_data_addr(DataAddr, !IO)
;
io.write_string("&", !IO),
output_data_addr(DataAddr, !IO)
)
;
io.write_string("\n", !IO),
output_rval(Rval, !IO)
).
trace_port_to_string(port_call) = "CALL".
trace_port_to_string(port_exit) = "EXIT".
trace_port_to_string(port_redo) = "REDO".
trace_port_to_string(port_fail) = "FAIL".
trace_port_to_string(port_exception) = "EXCEPTION".
trace_port_to_string(port_ite_cond) = "COND".
trace_port_to_string(port_ite_then) = "THEN".
trace_port_to_string(port_ite_else) = "ELSE".
trace_port_to_string(port_neg_enter) = "NEG_ENTER".
trace_port_to_string(port_neg_success) = "NEG_SUCCESS".
trace_port_to_string(port_neg_failure) = "NEG_FAILURE".
trace_port_to_string(port_disj_first) = "DISJ_FIRST".
trace_port_to_string(port_disj_later) = "DISJ_LATER".
trace_port_to_string(port_switch) = "SWITCH".
trace_port_to_string(port_nondet_foreign_proc_first) = "FOREIGN_PROC_FIRST".
trace_port_to_string(port_nondet_foreign_proc_later) = "FOREIGN_PROC_LATER".
trace_port_to_string(port_user) = "USER".
%-----------------------------------------------------------------------------%
:- pred output_proc_layout_data_defn(rtti_proc_label::in,
proc_layout_stack_traversal::in, maybe_proc_id_and_more::in,
decl_set::in, decl_set::out, io::di, io::uo) is det.
output_proc_layout_data_defn(RttiProcLabel, Traversal, MaybeRest,
!DeclSet, !IO) :-
output_layout_traversal_decls(Traversal, !DeclSet, !IO),
ProcLabel = make_proc_label_from_rtti(RttiProcLabel),
Kind = maybe_proc_layout_and_more_kind(MaybeRest, ProcLabel),
(
MaybeRest = no_proc_id,
output_proc_layout_data_defn_start(RttiProcLabel, Kind, Traversal,
!IO),
output_layout_no_proc_id_group(!IO),
output_proc_layout_data_defn_end(!IO)
;
MaybeRest = proc_id(MaybeProcStatic, MaybeExecTrace, ProcBodyBytes),
(
MaybeProcStatic = yes(ProcStatic),
output_proc_static_data_defn(RttiProcLabel, ProcStatic, !DeclSet,
!IO)
;
MaybeProcStatic = no
),
(
MaybeExecTrace = yes(ExecTrace),
HeadVarNums = ExecTrace ^ head_var_nums,
output_proc_layout_head_var_nums(RttiProcLabel, HeadVarNums,
!DeclSet, !IO),
VarNames = ExecTrace ^ var_names,
MaxVarNum = ExecTrace ^ max_var_num,
output_proc_layout_var_names(RttiProcLabel, VarNames, MaxVarNum,
!DeclSet, !IO),
output_layout_exec_trace_decls(RttiProcLabel, ExecTrace,
!DeclSet, !IO),
output_layout_exec_trace(RttiProcLabel, ExecTrace, !DeclSet, !IO)
;
MaybeExecTrace = no
),
(
ProcBodyBytes = []
;
ProcBodyBytes = [_ | _],
io.write_string("\n", !IO),
output_layout_name_storage_type_name(
proc_layout_body_bytecode(RttiProcLabel), yes, !IO),
io.write_string(" = {\n", !IO),
output_bytecodes_driver(ProcBodyBytes, !IO),
io.write_string("};\n\n", !IO)
),
output_proc_layout_data_defn_start(RttiProcLabel, Kind, Traversal,
!IO),
Origin = RttiProcLabel ^ pred_info_origin,
output_layout_proc_id_group(ProcLabel, Origin, !IO),
(
MaybeExecTrace = no,
io.write_string("NULL,\n", !IO)
;
MaybeExecTrace = yes(_),
io.write_string("&", !IO),
output_layout_name(proc_layout_exec_trace(RttiProcLabel), !IO),
io.write_string(",\n", !IO)
),
(
MaybeProcStatic = no,
io.write_string("NULL,\n", !IO)
;
MaybeProcStatic = yes(_),
io.write_string("&", !IO),
output_layout_name(proc_static(RttiProcLabel), !IO),
io.write_string(",\n", !IO)
),
(
ProcBodyBytes = [],
io.write_string("NULL\n", !IO)
;
ProcBodyBytes = [_ | _],
output_layout_name(proc_layout_body_bytecode(RttiProcLabel), !IO),
io.write_string("\n", !IO)
),
output_proc_layout_data_defn_end(!IO)
),
DeclId = decl_data_addr(layout_addr(proc_layout(RttiProcLabel, Kind))),
decl_set_insert(DeclId, !DeclSet).
:- func maybe_proc_layout_and_more_kind(maybe_proc_id_and_more,
proc_label) = proc_layout_kind.
maybe_proc_layout_and_more_kind(MaybeRest, ProcLabel) = Kind :-
(
MaybeRest = no_proc_id,
Kind = proc_layout_traversal
;
MaybeRest = proc_id(_, _, _),
Kind = proc_layout_proc_id(proc_label_user_or_uci(ProcLabel))
).
proc_label_user_or_uci(ordinary_proc_label(_, _, _, _, _, _)) = user.
proc_label_user_or_uci(special_proc_label(_, _, _, _, _, _)) = uci.
:- pred output_proc_layout_data_defn_start(rtti_proc_label::in,
proc_layout_kind::in, proc_layout_stack_traversal::in,
io::di, io::uo) is det.
output_proc_layout_data_defn_start(RttiProcLabel, Kind, Traversal, !IO) :-
io.write_string("\n", !IO),
output_layout_name_storage_type_name(proc_layout(RttiProcLabel, Kind),
yes, !IO),
io.write_string(" = {\n", !IO),
output_layout_traversal_group(Traversal, !IO).
:- pred output_proc_layout_data_defn_end(io::di, io::uo) is det.
output_proc_layout_data_defn_end(!IO) :-
io.write_string("};\n", !IO).
:- pred output_layout_traversal_decls(proc_layout_stack_traversal::in,
decl_set::in, decl_set::out, io::di, io::uo) is det.
output_layout_traversal_decls(Traversal, !DeclSet, !IO) :-
Traversal = proc_layout_stack_traversal(MaybeEntryLabel, _MaybeSuccipSlot,
_StackSlotCount, _Detism),
(
MaybeEntryLabel = yes(EntryLabel),
output_code_addr_decls(code_label(EntryLabel), !DeclSet, !IO)
;
MaybeEntryLabel = no
).
:- pred output_layout_traversal_group(proc_layout_stack_traversal::in,
io::di, io::uo) is det.
output_layout_traversal_group(Traversal, !IO) :-
Traversal = proc_layout_stack_traversal(MaybeEntryLabel, MaybeSuccipSlot,
StackSlotCount, Detism),
io.write_string("{\n", !IO),
(
MaybeEntryLabel = yes(EntryLabel),
output_code_addr(code_label(EntryLabel), !IO)
;
MaybeEntryLabel = no,
% The actual code address will be put into the structure
% by module initialization code.
io.write_string("NULL", !IO)
),
io.write_string(",\n{ ", !IO),
(
MaybeSuccipSlot = yes(SuccipSlot),
io.write_int(SuccipSlot, !IO)
;
MaybeSuccipSlot = no,
io.write_int(-1, !IO)
),
io.write_string(" },\n", !IO),
io.write_int(StackSlotCount, !IO),
io.write_string(",\n", !IO),
io.write_string(detism_to_c_detism(Detism), !IO),
io.write_string("\n},\n", !IO).
:- func detism_to_c_detism(determinism) = string.
detism_to_c_detism(detism_det) = "MR_DETISM_DET".
detism_to_c_detism(detism_semi) = "MR_DETISM_SEMI".
detism_to_c_detism(detism_non) = "MR_DETISM_NON".
detism_to_c_detism(detism_multi) = "MR_DETISM_MULTI".
detism_to_c_detism(detism_erroneous) = "MR_DETISM_ERRONEOUS".
detism_to_c_detism(detism_failure) = "MR_DETISM_FAILURE".
detism_to_c_detism(detism_cc_non) = "MR_DETISM_CCNON".
detism_to_c_detism(detism_cc_multi) = "MR_DETISM_CCMULTI".
:- pred output_layout_proc_id_group(proc_label::in, pred_origin::in,
io::di, io::uo) is det.
output_layout_proc_id_group(ProcLabel, Origin, !IO) :-
io.write_string("{\n", !IO),
output_proc_id(ProcLabel, Origin, !IO),
io.write_string("},\n", !IO).
:- pred output_layout_no_proc_id_group(io::di, io::uo) is det.
output_layout_no_proc_id_group(!IO) :-
io.write_string("-1\n", !IO).
:- pred output_layout_exec_trace_decls(rtti_proc_label::in,
proc_layout_exec_trace::in, decl_set::in, decl_set::out,
io::di, io::uo) is det.
output_layout_exec_trace_decls(RttiProcLabel, ExecTrace, !DeclSet, !IO) :-
ExecTrace = proc_layout_exec_trace(MaybeCallLabelLayout,
EventDataAddrs, MaybeTableInfo, _HeadVarNums, _VarNames, _MaxVarNum,
_MaxRegNum, _MaybeFromFullSlot, _MaybeIoSeqSlot,
_MaybeTrailSlot, _MaybeMaxfrSlot, _EvalMethod,
_MaybeCallTableSlot, _EffTraceLevel, _Flags),
ProcLabel = make_proc_label_from_rtti(RttiProcLabel),
ModuleName = get_defining_module_name(ProcLabel),
output_label_layout_addrs_in_vector(EventDataAddrs, "MR_DECL_LABEL_LAYOUT",
!IO),
EventDataDeclIds = list.map(wrap_decl_data_addr, EventDataAddrs),
list.foldl(decl_set_insert, EventDataDeclIds, !DeclSet),
(
MaybeCallLabelLayout = yes(CallLabelDetails),
CallLabelDetails = label_layout_details(CallProcLabel, LabelNum,
LabelVars),
CallLabelLayout = label_layout(CallProcLabel, LabelNum, LabelVars),
output_layout_decl(CallLabelLayout, !DeclSet, !IO)
;
MaybeCallLabelLayout = no
),
output_layout_decl(module_layout(ModuleName), !DeclSet, !IO),
(
MaybeTableInfo = yes(TableInfo),
output_data_addr_decls(TableInfo, !DeclSet, !IO)
;
MaybeTableInfo = no
).
:- func wrap_decl_data_addr(data_addr) = decl_id.
wrap_decl_data_addr(DataAddr) = decl_data_addr(DataAddr).
% The job of this predicate is to minimize stack space consumption in
% grades that do not allow output_bytecodes to be tail recursive.
%
:- pred output_bytecodes_driver(list(int)::in, io::di, io::uo) is det.
output_bytecodes_driver(Bytes, !IO) :-
(
Bytes = []
;
Bytes = [_ | _],
output_bytecodes(Bytes, BytesLeft, 0, 256, !IO),
output_bytecodes_driver(BytesLeft, !IO)
).
:- pred output_bytecodes(list(int)::in, list(int)::out, int::in, int::in,
io::di, io::uo) is det.
output_bytecodes(Bytes, BytesLeft, !.Seq, MaxSeq, !IO) :-
(
Bytes = [],
BytesLeft = []
;
Bytes = [Head | Tail],
( !.Seq < MaxSeq ->
io.write_int(Head, !IO),
io.write_char(',', !IO),
!:Seq = !.Seq + 1,
( unchecked_rem(!.Seq, 16) = 0 ->
io.write_char('\n', !IO)
;
true
),
output_bytecodes(Tail, BytesLeft, !.Seq, MaxSeq, !IO)
;
BytesLeft = Bytes
)
).
:- pred output_layout_exec_trace(rtti_proc_label::in,
proc_layout_exec_trace::in, decl_set::in, decl_set::out,
io::di, io::uo) is det.
output_layout_exec_trace(RttiProcLabel, ExecTrace, !DeclSet, !IO) :-
ExecTrace = proc_layout_exec_trace(MaybeCallLabelDetails,
EventDataAddrs, MaybeTableInfo, HeadVarNums, _VarNames, MaxVarNum,
MaxRegNum, MaybeFromFullSlot, MaybeIoSeqSlot, MaybeTrailSlot,
MaybeMaxfrSlot, EvalMethod, MaybeCallTableSlot, EffTraceLevel, Flags),
(
EventDataAddrs = []
;
EventDataAddrs = [_ | _],
io.write_string("\n", !IO),
output_layout_name_storage_type_name(
proc_layout_label_layouts(RttiProcLabel), yes, !IO),
io.write_string(" = {\n", !IO),
output_label_layout_addrs_in_vector(EventDataAddrs, "MR_LABEL_LAYOUT",
!IO),
io.write_string("};\n\n", !IO)
),
output_layout_name_storage_type_name(
proc_layout_exec_trace(RttiProcLabel), yes, !IO),
io.write_string(" = {\n", !IO),
(
MaybeCallLabelDetails = yes(CallLabelDetails),
io.write_string("MR_LABEL_LAYOUT_REF(", !IO),
CallLabelDetails = label_layout_details(CallProcLabel, CallLabelNum,
_),
output_label(internal_label(CallLabelNum, CallProcLabel), no, !IO),
io.write_string("),\n", !IO)
;
MaybeCallLabelDetails = no,
io.write_string("NULL,\n", !IO)
),
io.write_string("(const MR_ModuleLayout *) &", !IO),
ProcLabel = make_proc_label_from_rtti(RttiProcLabel),
ModuleName = get_defining_module_name(ProcLabel),
output_layout_name(module_layout(ModuleName), !IO),
io.write_string(",\n", !IO),
(
EventDataAddrs = [],
io.write_string("NULL,\n", !IO)
;
EventDataAddrs = [_ | _],
output_layout_name(proc_layout_label_layouts(RttiProcLabel), !IO),
io.write_string(",\n", !IO)
),
list.length(EventDataAddrs, NumEventDataAddrs),
io.write_int(NumEventDataAddrs, !IO),
io.write_string(",\n", !IO),
io.write_string("{ ", !IO),
(
MaybeTableInfo = yes(TableInfo),
io.write_string("(const void *) &", !IO),
output_data_addr(TableInfo, !IO)
;
MaybeTableInfo = no,
io.write_string("NULL", !IO)
),
io.write_string(" },\n", !IO),
output_layout_name(proc_layout_head_var_nums(RttiProcLabel), !IO),
io.write_string(",\n", !IO),
output_layout_name(proc_layout_var_names(RttiProcLabel), !IO),
io.write_string(",\n", !IO),
io.write_int(list.length(HeadVarNums), !IO),
io.write_string(",\n", !IO),
io.write_int(MaxVarNum, !IO),
io.write_string(",\n", !IO),
io.write_int(MaxRegNum, !IO),
io.write_string(",\n", !IO),
write_maybe_slot_num(MaybeFromFullSlot, !IO),
io.write_string(",\n", !IO),
write_maybe_slot_num(MaybeIoSeqSlot, !IO),
io.write_string(",\n", !IO),
write_maybe_slot_num(MaybeTrailSlot, !IO),
io.write_string(",\n", !IO),
write_maybe_slot_num(MaybeMaxfrSlot, !IO),
io.write_string(",\n", !IO),
io.write_string(eval_method_to_c_string(EvalMethod), !IO),
io.write_string(",\n", !IO),
write_maybe_slot_num(MaybeCallTableSlot, !IO),
io.write_string(",\n", !IO),
io.write_string(trace_level_rep(EffTraceLevel), !IO),
io.write_string(",\n", !IO),
io.write_int(Flags, !IO),
io.write_string("\n};\n", !IO).
:- pred write_maybe_slot_num(maybe(int)::in, io::di, io::uo) is det.
write_maybe_slot_num(yes(SlotNum), !IO) :-
io.write_int(SlotNum, !IO).
write_maybe_slot_num(no, !IO) :-
io.write_int(-1, !IO).
:- func eval_method_to_c_string(eval_method) = string.
eval_method_to_c_string(eval_normal) = "MR_EVAL_METHOD_NORMAL".
eval_method_to_c_string(eval_loop_check) = "MR_EVAL_METHOD_LOOP_CHECK".
eval_method_to_c_string(eval_memo) = "MR_EVAL_METHOD_MEMO".
eval_method_to_c_string(eval_minimal(MinimalMethod)) = Str :-
(
MinimalMethod = stack_copy,
Str = "MR_EVAL_METHOD_MINIMAL_STACK_COPY"
;
MinimalMethod = own_stacks_consumer,
Str = "MR_EVAL_METHOD_MINIMAL_OWN_STACKS_CONSUMER"
;
MinimalMethod = own_stacks_generator,
Str = "MR_EVAL_METHOD_MINIMAL_OWN_STACKS_GENERATOR"
).
eval_method_to_c_string(eval_table_io(Decl, Unitize)) = Str :-
(
Decl = table_io_proc,
Unitize = table_io_alone,
Str = "MR_EVAL_METHOD_TABLE_IO"
;
Decl = table_io_proc,
Unitize = table_io_unitize,
Str = "MR_EVAL_METHOD_TABLE_IO_UNITIZE"
;
Decl = table_io_decl,
Unitize = table_io_alone,
Str = "MR_EVAL_METHOD_TABLE_IO_DECL"
;
Decl = table_io_decl,
Unitize = table_io_unitize,
Str = "MR_EVAL_METHOD_TABLE_IO_UNITIZE_DECL"
).
:- pred output_proc_layout_head_var_nums(rtti_proc_label::in, list(int)::in,
decl_set::in, decl_set::out, io::di, io::uo) is det.
output_proc_layout_head_var_nums(ProcLabel, HeadVarNums, !DeclSet, !IO) :-
io.write_string("\n", !IO),
output_layout_name_storage_type_name(proc_layout_head_var_nums(ProcLabel),
yes, !IO),
io.write_string(" = {\n", !IO),
(
HeadVarNums = [],
% ANSI/ISO C doesn't allow empty arrays, so place a dummy value
% in the array.
io.write_string("0\n", !IO)
;
HeadVarNums = [_ | _],
list.foldl(output_number_in_vector, HeadVarNums, !IO)
),
io.write_string("};\n", !IO),
DeclId = decl_data_addr(layout_addr(proc_layout_head_var_nums(ProcLabel))),
decl_set_insert(DeclId, !DeclSet).
:- pred output_proc_layout_var_names(rtti_proc_label::in, list(int)::in,
int::in, decl_set::in, decl_set::out, io::di, io::uo) is det.
output_proc_layout_var_names(ProcLabel, VarNames, MaxVarNum, !DeclSet, !IO) :-
list.length(VarNames, VarNameCount),
expect(unify(VarNameCount, MaxVarNum), this_file,
"output_proc_layout_var_names: VarNameCount != MaxVarNum"),
io.write_string("\n", !IO),
output_layout_name_storage_type_name(proc_layout_var_names(ProcLabel), yes,
!IO),
io.write_string(" = {\n", !IO),
(
VarNames = [],
% ANSI/ISO C doesn't allow empty arrays, so place a dummy value
% in the array.
io.write_string("0\n", !IO)
;
VarNames = [_ | _],
list.foldl(output_number_in_vector, VarNames, !IO)
),
io.write_string("};\n", !IO),
DeclId = decl_data_addr(layout_addr(proc_layout_var_names(ProcLabel))),
decl_set_insert(DeclId, !DeclSet).
%-----------------------------------------------------------------------------%
:- pred output_closure_proc_id_data_defn(proc_label::in, int::in,
proc_label::in, module_name::in, string::in, int::in, pred_origin::in,
string::in, decl_set::in, decl_set::out, io::di, io::uo) is det.
output_closure_proc_id_data_defn(CallerProcLabel, SeqNo, ClosureProcLabel,
ModuleName, FileName, LineNumber, PredOrigin, GoalPath,
!DeclSet, !IO) :-
io.write_string("\n", !IO),
LayoutName = closure_proc_id(CallerProcLabel, SeqNo, ClosureProcLabel),
output_layout_name_storage_type_name(LayoutName, yes, !IO),
io.write_string(" = {\n{\n", !IO),
output_proc_id(ClosureProcLabel, PredOrigin, !IO),
io.write_string("},\n", !IO),
quote_and_write_string(sym_name_to_string(ModuleName), !IO),
io.write_string(",\n", !IO),
quote_and_write_string(FileName, !IO),
io.write_string(",\n", !IO),
io.write_int(LineNumber, !IO),
io.write_string(",\n", !IO),
quote_and_write_string(GoalPath, !IO),
io.write_string("\n};\n", !IO),
decl_set_insert(decl_data_addr(layout_addr(LayoutName)), !DeclSet).
:- pred output_proc_id(proc_label::in, pred_origin::in, io::di, io::uo) is det.
output_proc_id(ProcLabel, Origin, !IO) :-
(
ProcLabel = ordinary_proc_label(DefiningModule, PredOrFunc,
DeclaringModule, PredName0, Arity, Mode),
PredName = origin_name(Origin, PredName0),
output_pred_or_func(PredOrFunc, !IO),
io.write_string(",\n", !IO),
quote_and_write_string(sym_name_to_string(DeclaringModule), !IO),
io.write_string(",\n", !IO),
quote_and_write_string(sym_name_to_string(DefiningModule), !IO),
io.write_string(",\n", !IO),
quote_and_write_string(PredName, !IO),
io.write_string(",\n", !IO),
io.write_int(Arity, !IO),
io.write_string(",\n", !IO),
io.write_int(Mode, !IO),
io.write_string("\n", !IO)
;
ProcLabel = special_proc_label(DefiningModule, SpecialPredId,
TypeModule, TypeName, TypeArity, Mode),
TypeCtor = type_ctor(qualified(TypeModule, TypeName), TypeArity),
PredName0 = special_pred_name(SpecialPredId, TypeCtor),
PredName = origin_name(Origin, PredName0),
quote_and_write_string(TypeName, !IO),
io.write_string(",\n", !IO),
quote_and_write_string(sym_name_to_string(TypeModule), !IO),
io.write_string(",\n", !IO),
quote_and_write_string(sym_name_to_string(DefiningModule), !IO),
io.write_string(",\n", !IO),
quote_and_write_string(PredName, !IO),
io.write_string(",\n", !IO),
io.write_int(TypeArity, !IO),
io.write_string(",\n", !IO),
io.write_int(Mode, !IO),
io.write_string("\n", !IO)
).
:- func origin_name(pred_origin, string) = string.
origin_name(Origin, Name0) = Name :-
(
Origin = origin_lambda(FileName0, LineNum, SeqNo),
( string.append("IntroducedFrom", _, Name0) ->
string.replace_all(FileName0, ".", "_", FileName),
( SeqNo > 1 ->
string.format("lambda%d_%s_%d",
[i(SeqNo), s(FileName), i(LineNum)], Name)
;
string.format("lambda_%s_%d", [s(FileName), i(LineNum)], Name)
)
;
% If the lambda pred has a meaningful name, use it.
% This happens when the lambda is a partial application
% that happens to supply zero arguments.
Name = Name0
)
;
Origin = origin_special_pred(_SpecialPredId - _TypeCtor),
Name = Name0
% We can't use the following code until we have adapted the
% code in the runtime and trace directories to handle the names
% of special preds the same way as we do user-defined names.
% (
% SpecialPredId = unify,
% SpecialName = "unify"
% ;
% SpecialPredId = compare,
% SpecialName = "compare"
% ;
% SpecialPredId = index,
% SpecialName = "index"
% ;
% SpecialPredId = initialise,
% SpecialName = "init"
% ),
% TypeCtor = TypeSymName - TypeArity,
% TypeName = sym_name_to_string(TypeSymName),
% string.format("%s_for_%s_%d",
% [s(SpecialName), s(TypeName), i(TypeArity)], Name)
;
Origin = origin_transformed(Transform, OldOrigin, _),
OldName = origin_name(OldOrigin, ""),
( OldName = "" ->
Name = Name0
;
Name = OldName ++ "_" ++ pred_transform_name(Transform)
)
;
( Origin = origin_instance_method(_)
; Origin = origin_created(_)
; Origin = origin_assertion(_, _)
; Origin = origin_user(_)
),
Name = Name0
).
:- func pred_transform_name(pred_transformation) = string.
pred_transform_name(transform_higher_order_specialization(Seq)) =
"ho" ++ int_to_string(Seq).
pred_transform_name(transform_higher_order_type_specialization(Proc)) =
"hoproc" ++ int_to_string(Proc).
pred_transform_name(transform_type_specialization(Substs)) =
string.join_list("_", list.map(subst_to_name, Substs)).
pred_transform_name(transform_unused_argument_elimination(Posns)) =
"ua_" ++ string.join_list("_", list.map(int_to_string, Posns)).
pred_transform_name(transform_accumulator(Posns)) = "acc_" ++
string.join_list("_", list.map(int_to_string, Posns)).
pred_transform_name(transform_loop_invariant(Proc)) =
"inv_" ++ int_to_string(Proc).
pred_transform_name(transform_tuple(Proc)) = "tup_" ++ int_to_string(Proc).
pred_transform_name(transform_untuple(Proc)) = "untup_" ++ int_to_string(Proc).
pred_transform_name(transform_dependent_parallel_conjunction) =
"dep_par_conj_".
pred_transform_name(transform_return_via_ptr(ProcId, ArgPos)) =
"retptr_" ++ int_to_string(proc_id_to_int(ProcId)) ++ "_args"
++ ints_to_string(ArgPos).
pred_transform_name(transform_table_generator) = "table_gen".
pred_transform_name(transform_dnf(N)) = "dnf_" ++ int_to_string(N).
:- func ints_to_string(list(int)) = string.
ints_to_string([]) = "".
ints_to_string([N | Ns]) = "_" ++ int_to_string(N) ++ ints_to_string(Ns).
:- func subst_to_name(pair(int, mer_type)) = string.
subst_to_name(TVar - Type) =
string.format("%d/%s",
[i(TVar), s(mercury_type_to_string(varset.init, no, Type))]).
%-----------------------------------------------------------------------------%
% The version of the layout data structures -- useful for bootstrapping.
% If you write runtime code that checks this version number and can
% at least handle the previous version of the data structure,
% it makes it easier to bootstrap changes to these data structures.
%
% This number should be kept in sync with MR_LAYOUT_VERSION in
% runtime/mercury_stack_layout.h. This means you need to update
% the code in the runtime (including the trace directory) that uses
% layout structures to conform to whatever changes the new version
% introduces.
%
:- func layout_version_number = int.
layout_version_number = 3.
:- pred output_module_layout_data_defn(module_name::in, int::in,
string_with_0s::in, list(layout_name)::in, list(file_layout_data)::in,
trace_level::in, int::in, int::in, maybe(event_set_layout_data)::in,
decl_set::in, decl_set::out, io::di, io::uo) is det.
output_module_layout_data_defn(ModuleName, StringTableSize, StringTable,
ProcLayoutNames, FileLayouts, TraceLevel, SuppressedEvents,
NumLabels, MaybeEventSetLayout, !DeclSet, !IO) :-
output_module_string_table(ModuleName, StringTableSize, StringTable,
!DeclSet, !IO),
output_module_layout_proc_vector_defn(ModuleName, ProcLayoutNames,
ProcVectorName, !DeclSet, !IO),
output_file_layout_data_defns(ModuleName, 0, FileLayouts,
FileLayoutNames, !DeclSet, !IO),
output_file_layout_vector_data_defn(ModuleName, FileLayoutNames,
FileVectorName, !DeclSet, !IO),
io.write_string("\n", !IO),
LabelExecCountName = module_layout_label_exec_count(ModuleName,
NumLabels),
output_layout_name_storage_type_name(LabelExecCountName, yes, !IO),
io.write_string(";\n", !IO),
decl_set_insert(decl_data_addr(layout_addr(LabelExecCountName)), !DeclSet),
(
MaybeEventSetLayout = no
;
MaybeEventSetLayout = yes(EventSetDataLayout),
EventSetDataLayout =
event_set_layout_data(EventSetDataA, TypesRvalMap),
EventSetDataA = event_set_data(_EventSetName, EventSetDesc,
EventSpecsA, _MaxNumAttr),
output_event_set_desc_defn(ModuleName, EventSetDesc, !DeclSet, !IO),
output_event_specs_and_components(EventSpecsA, ModuleName,
TypesRvalMap, !DeclSet, !IO)
),
ModuleLayoutName = module_layout(ModuleName),
io.write_string("\n", !IO),
output_layout_name_storage_type_name(ModuleLayoutName, yes, !IO),
io.write_string(" = {\n", !IO),
io.write_int(layout_version_number, !IO),
io.write_string(",\n", !IO),
quote_and_write_string(sym_name_to_string(ModuleName), !IO),
io.write_string(",\n", !IO),
io.write_int(StringTableSize, !IO),
io.write_string(",\n", !IO),
ModuleStringTableName = module_layout_string_table(ModuleName),
output_layout_name(ModuleStringTableName, !IO),
io.write_string(",\n", !IO),
list.length(ProcLayoutNames, ProcLayoutVectorLength),
io.write_int(ProcLayoutVectorLength, !IO),
io.write_string(",\n", !IO),
output_layout_name(ProcVectorName, !IO),
io.write_string(",\n", !IO),
list.length(FileLayouts, FileLayoutVectorLength),
io.write_int(FileLayoutVectorLength, !IO),
io.write_string(",\n", !IO),
output_layout_name(FileVectorName, !IO),
io.write_string(",\n", !IO),
io.write_string(trace_level_rep(TraceLevel), !IO),
io.write_string(",\n", !IO),
io.write_int(SuppressedEvents, !IO),
io.write_string(",\n", !IO),
io.write_int(NumLabels, !IO),
io.write_string(",\n", !IO),
output_layout_name(LabelExecCountName, !IO),
io.write_string(",\n", !IO),
(
MaybeEventSetLayout = no,
io.write_string("NULL,\n", !IO),
io.write_string("NULL,\n", !IO),
io.write_string("0,\n", !IO),
io.write_string("0,\n", !IO),
io.write_string("NULL", !IO)
;
MaybeEventSetLayout = yes(EventSetDataLayoutB),
EventSetDataLayoutB =
event_set_layout_data(EventSetDataB, _TypesRvalMap),
EventSetDataB = event_set_data(EventSetName, _EventSetDesc,
EventSpecsB, MaxNumAttr),
quote_and_write_string(EventSetName, !IO),
io.write_string(",\n", !IO),
EventSetDescLayoutName = module_layout_event_set_desc(ModuleName),
output_layout_name(EventSetDescLayoutName, !IO),
io.write_string(",\n", !IO),
io.write_int(MaxNumAttr, !IO),
io.write_string(",\n", !IO),
io.write_int(list.length(EventSpecsB), !IO),
io.write_string(",\n", !IO),
EventSpecLayoutName = module_layout_event_specs(ModuleName),
output_layout_name(EventSpecLayoutName, !IO)
),
io.write_string("\n};\n", !IO),
decl_set_insert(decl_data_addr(layout_addr(ModuleLayoutName)), !DeclSet).
:- pred output_event_specs_and_components(list(event_spec)::in,
module_name::in, map(int, rval)::in,
decl_set::in, decl_set::out, io::di, io::uo) is det.
output_event_specs_and_components(EventSpecs, ModuleName, TypesRvalMap,
!DeclSet, !IO) :-
list.foldl2(output_event_spec_components(ModuleName), EventSpecs,
!DeclSet, !IO),
LayoutName = module_layout_event_specs(ModuleName),
DataAddr = layout_addr(LayoutName),
decl_set_insert(decl_data_addr(DataAddr), !DeclSet),
output_layout_name_storage_type_name(LayoutName, yes, !IO),
io.write_string(" = {\n", !IO),
io.write_list(EventSpecs, ",\n",
output_event_spec(ModuleName, TypesRvalMap), !IO),
io.write_string("\n};\n\n", !IO).
:- pred output_event_spec_components(module_name::in, event_spec::in,
decl_set::in, decl_set::out, io::di, io::uo) is det.
output_event_spec_components(ModuleName, EventSpec, !DeclSet, !IO) :-
EventSpec = event_spec(EventNumber, _EventName, _EventLineNumber,
Attrs, SynthOrder),
AttrNamesLayoutName =
module_layout_event_arg_names(ModuleName, EventNumber),
AttrNamesDataAddr = layout_addr(AttrNamesLayoutName),
decl_set_insert(decl_data_addr(AttrNamesDataAddr), !DeclSet),
output_layout_name_storage_type_name(AttrNamesLayoutName, yes, !IO),
io.write_string(" = {\n", !IO),
io.write_list(Attrs, ", ", output_attr_name, !IO),
io.write_string("\n};\n\n", !IO),
(
SynthOrder = []
;
SynthOrder = [_ | _],
list.foldl2(output_synth_attr_args(ModuleName, EventNumber),
Attrs, !DeclSet, !IO),
SynthAttrsLayoutName =
module_layout_event_synth_attrs(ModuleName, EventNumber),
SynthAttrsDataAddr = layout_addr(SynthAttrsLayoutName),
decl_set_insert(decl_data_addr(SynthAttrsDataAddr), !DeclSet),
output_layout_name_storage_type_name(SynthAttrsLayoutName, yes, !IO),
io.write_string(" = {\n", !IO),
io.write_list(Attrs, ",\n",
output_synth_attr(ModuleName, EventNumber), !IO),
io.write_string("\n};\n\n", !IO),
SynthOrderLayoutName =
module_layout_event_synth_order(ModuleName, EventNumber),
SynthOrderDataAddr = layout_addr(SynthOrderLayoutName),
decl_set_insert(decl_data_addr(SynthOrderDataAddr), !DeclSet),
output_layout_name_storage_type_name(SynthOrderLayoutName, yes, !IO),
io.write_string(" = {\n", !IO),
% The -1 acts as sentinel.
io.write_list(SynthOrder ++ [-1], ", ", io.write_int, !IO),
io.write_string("\n};\n\n", !IO)
).
:- pred output_attr_name(event_attribute::in, io::di, io::uo) is det.
output_attr_name(Attr, !IO) :-
io.write_string("""", !IO),
io.write_string(Attr ^ attr_name, !IO),
io.write_string("""", !IO).
:- pred output_synth_attr_args(module_name::in, int::in, event_attribute::in,
decl_set::in, decl_set::out, io::di, io::uo) is det.
output_synth_attr_args(ModuleName, EventNumber, Attr, !DeclSet, !IO) :-
MaybeSynthCall = Attr ^ attr_maybe_synth_call,
(
MaybeSynthCall = yes(SynthCall),
SynthCall = event_attr_synth_call(_FuncAttrNameNum, ArgAttrNameNums,
Order),
assoc_list.values(ArgAttrNameNums, ArgAttrNums),
AttrNumber = Attr ^ attr_num,
ArgsLayoutName = module_layout_event_synth_attr_args(ModuleName,
EventNumber, AttrNumber),
ArgsDataAddr = layout_addr(ArgsLayoutName),
decl_set_insert(decl_data_addr(ArgsDataAddr), !DeclSet),
output_layout_name_storage_type_name(ArgsLayoutName, yes, !IO),
io.write_string(" =\n{ ", !IO),
io.write_list(ArgAttrNums, ", ", io.write_int, !IO),
io.write_string(" };\n\n", !IO),
OrderLayoutName = module_layout_event_synth_attr_order(ModuleName,
EventNumber, AttrNumber),
OrderDataAddr = layout_addr(OrderLayoutName),
decl_set_insert(decl_data_addr(OrderDataAddr), !DeclSet),
output_layout_name_storage_type_name(OrderLayoutName, yes, !IO),
io.write_string(" =\n{ ", !IO),
OrderSentinel = Order ++ [-1],
io.write_list(OrderSentinel, ", ", io.write_int, !IO),
io.write_string(" };\n\n", !IO)
;
MaybeSynthCall = no
).
:- pred output_synth_attr(module_name::in, int::in, event_attribute::in,
io::di, io::uo) is det.
output_synth_attr(ModuleName, EventNumber, Attr, !IO) :-
io.write_string("{ ", !IO),
MaybeSynthCall = Attr ^ attr_maybe_synth_call,
(
MaybeSynthCall = yes(SynthCall),
SynthCall = event_attr_synth_call(_FuncAttrName - FuncAttrNum,
ArgAttrNameNums, _EvalOrder),
io.write_int(FuncAttrNum, !IO),
io.write_string(", ", !IO),
io.write_int(list.length(ArgAttrNameNums), !IO),
io.write_string(",\n ", !IO),
AttrNumber = Attr ^ attr_num,
ArgsLayoutName = module_layout_event_synth_attr_args(ModuleName,
EventNumber, AttrNumber),
output_layout_name(ArgsLayoutName, !IO),
io.write_string(",\n ", !IO),
OrderLayoutName = module_layout_event_synth_attr_order(ModuleName,
EventNumber, AttrNumber),
output_layout_name(OrderLayoutName, !IO)
;
MaybeSynthCall = no,
io.write_string("-1, -1, NULL, NULL", !IO)
),
io.write_string(" }", !IO).
:- pred output_event_spec(module_name::in, map(int, rval)::in, event_spec::in,
io::di, io::uo) is det.
output_event_spec(ModuleName, TypesRvalMap, EventSpec, !IO) :-
EventSpec = event_spec(EventNumber, EventName, _EventLineNumber, Attrs,
SynthOrder),
map.lookup(TypesRvalMap, EventNumber, TypesRval),
io.write_string("{ """, !IO),
io.write_string(EventName, !IO),
io.write_string(""", ", !IO),
io.write_int(list.length(Attrs), !IO),
io.write_string(",\n\t", !IO),
AttrNamesLayoutName =
module_layout_event_arg_names(ModuleName, EventNumber),
output_layout_name(AttrNamesLayoutName, !IO),
io.write_string(",\n\t(MR_TypeInfo *) ", !IO),
output_rval_as_addr(TypesRval, !IO),
io.write_string(",\n\t", !IO),
(
SynthOrder = [],
io.write_string("NULL, NULL }", !IO)
;
SynthOrder = [_ | _],
SynthAttrsLayoutName =
module_layout_event_synth_attrs(ModuleName, EventNumber),
SynthOrderLayoutName =
module_layout_event_synth_order(ModuleName, EventNumber),
output_layout_name(SynthAttrsLayoutName, !IO),
io.write_string(",\n\t", !IO),
output_layout_name(SynthOrderLayoutName, !IO),
io.write_string(" }", !IO)
).
:- pred output_module_layout_proc_vector_defn(module_name::in,
list(layout_name)::in, layout_name::out, decl_set::in, decl_set::out,
io::di, io::uo) is det.
output_module_layout_proc_vector_defn(ModuleName, ProcLayoutNames,
VectorName, !DeclSet, !IO) :-
list.foldl2(output_layout_decl, ProcLayoutNames, !DeclSet, !IO),
VectorName = module_layout_proc_vector(ModuleName),
io.write_string("\n", !IO),
output_layout_name_storage_type_name(VectorName, yes, !IO),
io.write_string(" = {\n", !IO),
(
ProcLayoutNames = [],
% ANSI/ISO C doesn't allow empty arrays, so place a dummy value
% in the array.
io.write_string("NULL\n", !IO)
;
ProcLayoutNames = [_ | _],
list.foldl(output_proc_layout_name_in_vector, ProcLayoutNames, !IO)
),
io.write_string("};\n", !IO),
decl_set_insert(decl_data_addr(layout_addr(VectorName)), !DeclSet).
:- pred output_proc_layout_name_in_vector(layout_name::in, io::di, io::uo)
is det.
output_proc_layout_name_in_vector(LayoutName, !IO) :-
( LayoutName = proc_layout(RttiProcLabel, _) ->
ProcLabel = make_proc_label_from_rtti(RttiProcLabel),
io.write_string("MR_PROC_LAYOUT1(", !IO),
output_proc_label_no_prefix(ProcLabel, !IO),
io.write_string(")\n", !IO)
;
unexpected(this_file,
"output_proc_layout_name_in_vector: not proc layout")
).
%-----------------------------------------------------------------------------%
:- pred output_event_set_desc_defn(module_name::in, string::in,
decl_set::in, decl_set::out, io::di, io::uo) is det.
output_event_set_desc_defn(ModuleName, EventSetDesc, !DeclSet, !IO) :-
LayoutName = module_layout_event_set_desc(ModuleName),
io.write_string("\n", !IO),
output_layout_name_storage_type_name(LayoutName, yes, !IO),
io.write_string(" = {", !IO),
output_module_string_table_strings(EventSetDesc, [], !IO),
io.write_string("};\n", !IO),
decl_set_insert(decl_data_addr(layout_addr(LayoutName)), !DeclSet).
:- pred output_module_string_table(module_name::in,
int::in, string_with_0s::in, decl_set::in, decl_set::out,
io::di, io::uo) is det.
output_module_string_table(ModuleName, _StringTableSize,
string_with_0s(StringTable0), !DeclSet, !IO) :-
TableName = module_layout_string_table(ModuleName),
io.write_string("\n", !IO),
output_layout_name_storage_type_name(TableName, yes, !IO),
io.write_string(" = {", !IO),
%
% The string table cannot be zero size; it must contain at least an
% empty string.
%
( StringTable0 = [], FirstString = "", Rest = []
; StringTable0 = [FirstString | Rest]
),
output_module_string_table_strings(FirstString, Rest, !IO),
io.write_string("};\n", !IO),
decl_set_insert(decl_data_addr(layout_addr(TableName)), !DeclSet).
:- pred output_module_string_table_strings(string::in, list(string)::in,
io::di, io::uo) is det.
output_module_string_table_strings(String, [], !IO) :-
output_module_string_table_chars(0, length(String) - 1, String, !IO).
output_module_string_table_strings(String, [Next | Rest], !IO) :-
output_module_string_table_chars(0, length(String) - 1, String, !IO),
io.write_string(",\n", !IO),
output_module_string_table_strings(Next, Rest, !IO).
:- pred output_module_string_table_chars(int::in, int::in, string::in,
io::di, io::uo) is det.
output_module_string_table_chars(CurIndex, MaxIndex, String, !IO) :-
( CurIndex =< MaxIndex ->
( CurIndex mod 10 = 0 ->
io.nl(!IO)
;
true
),
string.unsafe_index(String, CurIndex, Char),
io.write_char('''', !IO),
c_util.output_quoted_char(Char, !IO),
io.write_char('''', !IO),
io.write_string(", ", !IO),
output_module_string_table_chars(CurIndex + 1, MaxIndex, String, !IO)
;
io.write_char('''', !IO),
c_util.output_quoted_char(char.det_from_int(0), !IO),
io.write_char('''', !IO)
).
%-----------------------------------------------------------------------------%
:- pred output_file_layout_vector_data_defn(module_name::in,
list(layout_name)::in, layout_name::out, decl_set::in, decl_set::out,
io::di, io::uo) is det.
output_file_layout_vector_data_defn(ModuleName, FileLayoutNames, VectorName,
!DeclSet, !IO) :-
list.foldl2(output_layout_decl, FileLayoutNames, !DeclSet, !IO),
VectorName = module_layout_file_vector(ModuleName),
io.write_string("\n", !IO),
output_layout_name_storage_type_name(VectorName, yes, !IO),
io.write_string(" = {\n", !IO),
(
FileLayoutNames = [],
% ANSI/ISO C doesn't allow empty arrays, so place a dummy value
% in the array.
io.write_string("NULL\n", !IO)
;
FileLayoutNames = [_ | _],
list.foldl(output_layout_name_in_vector("&"), FileLayoutNames, !IO)
),
io.write_string("};\n", !IO),
decl_set_insert(decl_data_addr(layout_addr(VectorName)), !DeclSet).
:- pred output_file_layout_data_defns(module_name::in, int::in,
list(file_layout_data)::in, list(layout_name)::out,
decl_set::in, decl_set::out, io::di, io::uo) is det.
output_file_layout_data_defns(_, _, [], [], !DeclSet, !IO).
output_file_layout_data_defns(ModuleName, FileNum, [FileLayout | FileLayouts],
[FileLayoutName | FileLayoutNames], !DeclSet, !IO) :-
output_file_layout_data_defn(ModuleName, FileNum, FileLayout,
FileLayoutName, !DeclSet, !IO),
output_file_layout_data_defns(ModuleName, FileNum + 1, FileLayouts,
FileLayoutNames, !DeclSet, !IO).
:- pred output_file_layout_data_defn(module_name::in, int::in,
file_layout_data::in, layout_name::out,
decl_set::in, decl_set::out, io::di, io::uo) is det.
output_file_layout_data_defn(ModuleName, FileNum, FileLayout, FileLayoutName,
!DeclSet, !IO) :-
FileLayout = file_layout_data(FileName, LineNoLabelList),
list.map2(line_no_label_to_label_layout_addr, LineNoLabelList,
LineNos, LabelLayoutAddrs),
list.foldl2(output_data_addr_decls, LabelLayoutAddrs, !DeclSet, !IO),
list.length(LineNoLabelList, VectorLengths),
output_file_layout_line_number_vector_defn(ModuleName, FileNum,
LineNos, LineNumberVectorName, !DeclSet, !IO),
output_file_layout_label_layout_vector_defn(ModuleName, FileNum,
LabelLayoutAddrs, LabelVectorName, !DeclSet, !IO),
FileLayoutName = file_layout(ModuleName, FileNum),
io.write_string("\n", !IO),
output_layout_name_storage_type_name(FileLayoutName, yes, !IO),
io.write_string(" = {\n", !IO),
quote_and_write_string(FileName, !IO),
io.write_string(",\n", !IO),
io.write_int(VectorLengths, !IO),
io.write_string(",\n", !IO),
output_layout_name(LineNumberVectorName, !IO),
io.write_string(",\n", !IO),
output_layout_name(LabelVectorName, !IO),
io.write_string("\n};\n", !IO),
decl_set_insert(decl_data_addr(layout_addr(FileLayoutName)), !DeclSet).
:- pred output_file_layout_line_number_vector_defn(module_name::in, int::in,
list(int)::in, layout_name::out, decl_set::in, decl_set::out,
io::di, io::uo) is det.
output_file_layout_line_number_vector_defn(ModuleName, FileNum, LineNumbers,
LayoutName, !DeclSet, !IO) :-
LayoutName = file_layout_line_number_vector(ModuleName, FileNum),
io.write_string("\n", !IO),
output_layout_name_storage_type_name(LayoutName, yes, !IO),
io.write_string(" = {\n", !IO),
(
LineNumbers = [],
% ANSI/ISO C doesn't allow empty arrays, so place a dummy value
% in the array.
io.write_string("0\n", !IO)
;
LineNumbers = [_ | _],
list.foldl(output_number_in_vector, LineNumbers, !IO)
),
io.write_string("};\n", !IO),
decl_set_insert(decl_data_addr(layout_addr(LayoutName)), !DeclSet).
:- pred output_file_layout_label_layout_vector_defn(module_name::in, int::in,
list(data_addr)::in, layout_name::out, decl_set::in, decl_set::out,
io::di, io::uo) is det.
output_file_layout_label_layout_vector_defn(ModuleName, FileNum, LabelAddrs,
LayoutName, !DeclSet, !IO) :-
LayoutName = file_layout_label_layout_vector(ModuleName, FileNum),
io.write_string("\n", !IO),
output_layout_name_storage_type_name(LayoutName, yes, !IO),
io.write_string(" = {\n", !IO),
(
LabelAddrs = [],
% ANSI/ISO C doesn't allow empty arrays, so place a dummy value
% in the array.
io.write_string("NULL\n", !IO)
;
LabelAddrs = [_ | _],
output_label_layout_addrs_in_vector(LabelAddrs, "MR_LABEL_LAYOUT", !IO)
),
io.write_string("};\n", !IO),
decl_set_insert(decl_data_addr(layout_addr(LayoutName)), !DeclSet).
%-----------------------------------------------------------------------------%
:- pred output_label_layout_addrs_in_vector(list(data_addr)::in, string::in,
io::di, io::uo) is det.
output_label_layout_addrs_in_vector([], _, !IO).
output_label_layout_addrs_in_vector([DataAddr | DataAddrs], Macro, !IO) :-
(
DataAddr = layout_addr(LayoutName),
LayoutName = label_layout(ProcLabel, LabelNum, label_has_var_info)
->
groupable_labels(ProcLabel, 1, _N, [LabelNum], RevLabelNums,
DataAddrs, RemainingDataAddrs),
list.reverse(RevLabelNums, LabelNums),
io.write_string(Macro, !IO),
io.write_int(list.length(LabelNums), !IO),
io.write_string("(", !IO),
output_proc_label_no_prefix(ProcLabel, !IO),
io.write_string(",", !IO),
io.write_list(LabelNums, ",", io.write_int, !IO),
io.write_string(")\n", !IO),
output_label_layout_addrs_in_vector(RemainingDataAddrs, Macro, !IO)
;
unexpected(this_file,
"output_label_layout_addrs_in_vector: not label layout")
).
:- pred groupable_labels(proc_label::in, int::in, int::out,
list(int)::in, list(int)::out, list(data_addr)::in, list(data_addr)::out)
is det.
groupable_labels(GroupProcLabel, !Count, !RevLabelsNums, !DataAddrs) :-
(
!.DataAddrs = []
;
!.DataAddrs = [DataAddr | DataAddrsTail],
(
DataAddr = layout_addr(LayoutName),
LayoutName = label_layout(ProcLabel, LabelNum, label_has_var_info)
->
% There must be a macro of the form MR_LABEL_LAYOUT<n> and
% MR_DECL_LABEL_LAYOUT<n> for every <n> up to MaxChunkSize.
MaxChunkSize = 9,
(
% We cannot group together labels from different procedures.
ProcLabel = GroupProcLabel,
% Leave room for the one we're adding.
!.Count < MaxChunkSize
->
!:DataAddrs = DataAddrsTail,
!:Count = !.Count + 1,
!:RevLabelsNums = [LabelNum | !.RevLabelsNums],
groupable_labels(GroupProcLabel, !Count, !RevLabelsNums,
!DataAddrs)
;
true
)
;
unexpected(this_file, "groupable_labels: not label layout")
)
).
%-----------------------------------------------------------------------------%
:- pred line_no_label_to_label_layout_addr(pair(int, layout_name)::in,
int::out, data_addr::out) is det.
line_no_label_to_label_layout_addr(LineNo - LabelLayout, LineNo, DataAddr) :-
DataAddr = layout_addr(LabelLayout).
:- pred quote_and_write_string(string::in, io::di, io::uo) is det.
quote_and_write_string(String, !IO) :-
io.write_string("""", !IO),
c_util.output_quoted_string(String, !IO),
io.write_string("""", !IO).
:- pred output_number_in_vector(int::in, io::di, io::uo) is det.
output_number_in_vector(Num, !IO) :-
io.write_int(Num, !IO),
io.write_string(",\n", !IO).
:- pred output_layout_name_in_vector(string::in, layout_name::in,
io::di, io::uo) is det.
output_layout_name_in_vector(Prefix, Name, !IO) :-
io.write_string(Prefix, !IO),
output_layout_name(Name, !IO),
io.write_string(",\n", !IO).
:- pred output_data_addr_in_vector(string::in, data_addr::in,
io::di, io::uo) is det.
output_data_addr_in_vector(Prefix, DataAddr, !IO) :-
io.write_string(Prefix, !IO),
output_data_addr(DataAddr, !IO),
io.write_string(",\n", !IO).
%-----------------------------------------------------------------------------%
:- pred output_proc_static_data_defn(rtti_proc_label::in,
proc_layout_proc_static::in, decl_set::in, decl_set::out,
io::di, io::uo) is det.
output_proc_static_data_defn(RttiProcLabel, ProcLayoutProcStatic,
!DeclSet, !IO) :-
ProcLayoutProcStatic = proc_layout_proc_static(HLDSProcStatic,
DeepExcpVars),
HLDSProcStatic = hlds_proc_static(FileName, LineNumber, IsInInterface,
CallSites),
list.foldl2(output_call_site_static_decl, CallSites, !DeclSet, !IO),
output_call_site_static_array(RttiProcLabel, CallSites, !DeclSet, !IO),
LayoutName = proc_static(RttiProcLabel),
io.write_string("\n", !IO),
output_layout_name_storage_type_name(LayoutName, yes, !IO),
io.write_string(" = {\n", !IO),
quote_and_write_string(FileName, !IO),
io.write_string(",\n", !IO),
io.write_int(LineNumber, !IO),
io.write_string(",\n", !IO),
(
IsInInterface = yes,
io.write_string("MR_TRUE", !IO)
;
IsInInterface = no,
io.write_string("MR_FALSE", !IO)
),
io.write_string(",\n", !IO),
io.write_int(list.length(CallSites), !IO),
io.write_string(",\n", !IO),
CallSitesLayoutName = proc_static_call_sites(RttiProcLabel),
output_layout_name(CallSitesLayoutName, !IO),
io.write_string(",\n#ifdef MR_USE_ACTIVATION_COUNTS\n", !IO),
io.write_string("0,\n", !IO),
io.write_string("#endif\n", !IO),
io.write_string("NULL,\n", !IO),
DeepExcpVars = deep_excp_slots(TopCSDSlot, MiddleCSDSlot,
OldOutermostSlot),
io.write_int(TopCSDSlot, !IO),
io.write_string(",\n\t", !IO),
io.write_int(MiddleCSDSlot, !IO),
io.write_string(",\n\t", !IO),
io.write_int(OldOutermostSlot, !IO),
io.write_string("\n};\n", !IO),
decl_set_insert(decl_data_addr(layout_addr(LayoutName)), !DeclSet).
:- pred output_call_site_static_array(rtti_proc_label::in,
list(call_site_static_data)::in, decl_set::in, decl_set::out,
io::di, io::uo) is det.
output_call_site_static_array(RttiProcLabel, CallSites, !DeclSet, !IO) :-
LayoutName = proc_static_call_sites(RttiProcLabel),
io.write_string("\n", !IO),
output_layout_name_storage_type_name(LayoutName, yes, !IO),
io.write_string(" = {\n", !IO),
list.foldl2(output_call_site_static, CallSites, 0, _, !IO),
io.write_string("};\n", !IO),
decl_set_insert(decl_data_addr(layout_addr(LayoutName)), !DeclSet).
:- pred output_call_site_static(call_site_static_data::in, int::in, int::out,
io::di, io::uo) is det.
output_call_site_static(CallSiteStatic, Index, Index + 1, !IO) :-
io.write_string("{ /* ", !IO),
io.write_int(Index, !IO),
io.write_string(" */ ", !IO),
(
CallSiteStatic = normal_call(Callee, TypeSubst, FileName, LineNumber,
GoalPath),
io.write_string("MR_normal_call, (MR_ProcLayout *)\n&", !IO),
CalleeProcLabel = make_proc_label_from_rtti(Callee),
CalleeUserOrUci = proc_label_user_or_uci(CalleeProcLabel),
output_layout_name(proc_layout(Callee,
proc_layout_proc_id(CalleeUserOrUci)), !IO),
( TypeSubst = "" ->
io.write_string(", NULL, ", !IO)
;
io.write_string(",\n""", !IO),
io.write_string(TypeSubst, !IO),
io.write_string(""", ", !IO)
)
;
CallSiteStatic = special_call(FileName, LineNumber, GoalPath),
io.write_string("MR_special_call, NULL, NULL, ", !IO)
;
CallSiteStatic = higher_order_call(FileName, LineNumber, GoalPath),
io.write_string("MR_higher_order_call, NULL, NULL, ", !IO)
;
CallSiteStatic = method_call(FileName, LineNumber, GoalPath),
io.write_string("MR_method_call, NULL, NULL, ", !IO)
;
CallSiteStatic = callback(FileName, LineNumber, GoalPath),
io.write_string("MR_callback, NULL, NULL, ", !IO)
),
io.write_string("""", !IO),
io.write_string(FileName, !IO),
io.write_string(""", ", !IO),
io.write_int(LineNumber, !IO),
io.write_string(", """, !IO),
io.write_string(goal_path_to_string(GoalPath), !IO),
io.write_string(""" },\n", !IO).
:- pred output_call_site_static_decl(call_site_static_data::in,
decl_set::in, decl_set::out, io::di, io::uo) is det.
output_call_site_static_decl(CallSiteStatic, !DeclSet, !IO) :-
(
CallSiteStatic = normal_call(Callee, _, _, _, _),
CalleeProcLabel = make_proc_label_from_rtti(Callee),
CalleeUserOrUci = proc_label_user_or_uci(CalleeProcLabel),
output_maybe_layout_name_decl(proc_layout(Callee,
proc_layout_proc_id(CalleeUserOrUci)), !DeclSet, !IO)
;
CallSiteStatic = special_call(_, _, _)
;
CallSiteStatic = higher_order_call(_, _, _)
;
CallSiteStatic = method_call(_, _, _)
;
CallSiteStatic = callback(_, _, _)
).
%-----------------------------------------------------------------------------%
:- pred output_table_io_decl(rtti_proc_label::in, proc_layout_kind::in,
int::in, rval::in, rval::in, decl_set::in, decl_set::out,
io::di, io::uo) is det.
output_table_io_decl(RttiProcLabel, ProcLayoutKind, NumPTIs,
PTIVectorRval, TypeParamsRval, !DeclSet, !IO) :-
output_rval_decls(PTIVectorRval, !DeclSet, !IO),
LayoutName = table_io_decl(RttiProcLabel),
ProcLayoutName = proc_layout(RttiProcLabel, ProcLayoutKind),
output_layout_decl(ProcLayoutName, !DeclSet, !IO),
io.write_string("\n", !IO),
output_layout_name_storage_type_name(LayoutName, yes, !IO),
io.write_string(" = {\n(const MR_ProcLayout *) &", !IO),
output_layout_name(ProcLayoutName, !IO),
io.write_string(",\n", !IO),
io.write_int(NumPTIs, !IO),
io.write_string(",\n(const MR_PseudoTypeInfo *) ", !IO),
output_rval(PTIVectorRval, !IO),
io.write_string(",\n(const MR_TypeParamLocns *) ", !IO),
output_rval(TypeParamsRval, !IO),
io.write_string("\n};\n", !IO),
decl_set_insert(decl_data_addr(layout_addr(LayoutName)), !DeclSet).
%-----------------------------------------------------------------------------%
output_pred_or_func(PredOrFunc, !IO) :-
(
PredOrFunc = pf_predicate,
io.write_string("MR_PREDICATE", !IO)
;
PredOrFunc = pf_function,
io.write_string("MR_FUNCTION", !IO)
).
%-----------------------------------------------------------------------------%
:- func this_file = string.
this_file = "layout_out.m".
%-----------------------------------------------------------------------------%