[m-dev.] for review: clean up MLDS init functions
Fergus Henderson
fjh at cs.mu.OZ.AU
Thu Nov 9 02:43:27 AEDT 2000
Zoltan, could you please review this one?
----------
Estimated hours taken: 1
Modify the MLDS back-end so that it generates more readable
code for the module initialization functions.
compiler/mlds_to_c.m:
In the initialization functions, output calls to MR_init_entry()
only if they are needed (i.e. if profiling is enabled).
Likewise output the code that ensures that the initialization
is only run once only if the initialization is non-empty.
Use `bool', `TRUE', and `FALSE' rather than `int', 0, and 1
for the `initialised' variable.
compiler/ml_code_gen.m:
Document the principle that the MLDS back-end should avoid
relying on macros and conditional compilation, to improve
readability and to make it easier to target languages like Java.
runtime/mercury_conf_param.h:
runtime/mercury_goto.h:
Add some comments about the MLDS back-end.
Workspace: /home/pgrad/fjh/ws/hg
Index: compiler/ml_code_gen.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/ml_code_gen.m,v
retrieving revision 1.64
diff -u -d -r1.64 ml_code_gen.m
--- compiler/ml_code_gen.m 2000/11/08 07:23:06 1.64
+++ compiler/ml_code_gen.m 2000/11/08 08:47:54
@@ -14,8 +14,20 @@
% very low-level code. This code generator instead compiles to MLDS,
% generating much higher-level code than the original code generator.
-% For nondeterministic predicates, we generate code using an explicit
-% continuation passing style. Each nondeterministic predicate gets
+% One of the aims of the MLDS is to be able to generated human-readable
+% code in languages like C or Java. This means that unlike the LLDS back-end,
+% we do not want to rely on macros or conditional compilation. If the
+% final code is going to depend on the setting of some compilation option,
+% our philosophy is to reflect that change in the generated MLDS and C code
+% where possible, rather than generating C code which calls macros that do
+% different things in different grades. This is important both for
+% readability of the generated code, and to make sure that we can easily
+% adapt the MLDS code generator to target languages like Java that don't
+% support macros or conditional compilation.
+
+% A big challenge in generating MLDS code is handling nondeterminism.
+% For nondeterministic procedures, we generate code using an explicit
+% continuation passing style. Each nondeterministic procedures gets
% translated into a function which takes an extra parameter which is a
% function pointer that points to the success continuation. On success,
% the function calls its success continuation, and on failure it returns.
@@ -621,11 +633,11 @@
%-----------------------------------------------------------------------------%
-% XXX This back-end is still not yet complete.
+% This back-end is still not yet 100% complete.
%
% Done:
% - function prototypes
-% - code generation for det, semidet, and nondet predicates:
+% - code generation for det, semidet, and nondet predicates/functions:
% - conjunctions
% - disjunctions
% - negation
Index: compiler/mlds_to_c.m
===================================================================
RCS file: /home/mercury1/repository/mercury/compiler/mlds_to_c.m,v
retrieving revision 1.65
diff -u -d -r1.65 mlds_to_c.m
--- compiler/mlds_to_c.m 2000/11/08 07:23:08 1.65
+++ compiler/mlds_to_c.m 2000/11/08 12:40:08
@@ -164,6 +164,22 @@
Defn = mlds__defn(Name, _Context, _Flags, _Body),
Name = type(_, _).
+:- pred defn_is_function(mlds__defn).
+:- mode defn_is_function(in) is semidet.
+
+defn_is_function(Defn) :-
+ Defn = mlds__defn(Name, _Context, _Flags, _Body),
+ Name = function(_, _, _, _).
+
+:- pred defn_is_type_ctor_info(mlds__defn).
+:- mode defn_is_type_ctor_info(in) is semidet.
+
+defn_is_type_ctor_info(Defn) :-
+ Defn = mlds__defn(_Name, _Context, _Flags, Body),
+ Body = mlds__data(Type, _),
+ Type = mlds__rtti_type(RttiName),
+ RttiName = type_ctor_info.
+
:- pred defn_is_commit_type_var(mlds__defn).
:- mode defn_is_commit_type_var(in) is semidet.
@@ -237,13 +253,17 @@
{ list__filter(defn_is_type, PrivateDefns, PrivateTypeDefns,
PrivateNonTypeDefns) },
{ list__filter(defn_is_type, Defns, _TypeDefns, NonTypeDefns) },
+ { list__filter(defn_is_function, NonTypeDefns, FuncDefns) },
+ { list__filter(defn_is_type_ctor_info, NonTypeDefns,
+ TypeCtorInfoDefns) },
{ MLDS_ModuleName = mercury_module_name_to_mlds(ModuleName) },
mlds_output_defns(Indent, MLDS_ModuleName, PrivateTypeDefns), io__nl,
mlds_output_decls(Indent, MLDS_ModuleName, PrivateNonTypeDefns), io__nl,
mlds_output_c_defns(MLDS_ModuleName, Indent, ForeignCode), io__nl,
mlds_output_defns(Indent, MLDS_ModuleName, NonTypeDefns), io__nl,
- mlds_output_init_fn_defns(MLDS_ModuleName, NonTypeDefns, Defns), io__nl,
+ mlds_output_init_fn_defns(MLDS_ModuleName, FuncDefns,
+ TypeCtorInfoDefns), io__nl,
mlds_output_src_end(Indent, ModuleName).
:- pred mlds_output_hdr_start(indent, mercury_module_name,
@@ -345,28 +365,43 @@
:- pred mlds_output_init_fn_defns(mlds_module_name::in, mlds__defns::in,
mlds__defns::in, io__state::di, io__state::uo) is det.
-mlds_output_init_fn_defns(ModuleName, NonTypeDefns, Defns) -->
+mlds_output_init_fn_defns(ModuleName, FuncDefns, TypeCtorInfoDefns) -->
output_init_fn_name(ModuleName, ""),
io__write_string("\n{\n"),
- io__write_strings(["\tstatic int initialised = 0;\n",
- "\tif (initialised) return;\n",
- "\tinitialised = 1;\n\n"]),
- mlds_output_init_main_fn(ModuleName, NonTypeDefns),
- io__write_string("\n}\n"),
+ io_get_globals(Globals),
+ (
+ { need_to_init_entries(Globals) },
+ { FuncDefns \= [] }
+ ->
+ io__write_strings(["\tstatic bool initialised = FALSE;\n",
+ "\tif (initialised) return;\n",
+ "\tinitialised = TRUE;\n\n"]),
+ mlds_output_calls_to_init_entry(ModuleName, FuncDefns)
+ ;
+ []
+ ),
+ io__write_string("}\n\n"),
output_init_fn_name(ModuleName, "_type_tables"),
io__write_string("\n{\n"),
- io__write_strings(["\tstatic int initialised = 0;\n",
- "\tif (initialised) return;\n",
- "\tinitialised = 1;\n\n"]),
- mlds_output_init_type_table_fn(ModuleName, Defns),
- io__write_string("\n}\n"),
+ (
+ { TypeCtorInfoDefns \= [] }
+ ->
+ io__write_strings(["\tstatic bool initialised = FALSE;\n",
+ "\tif (initialised) return;\n",
+ "\tinitialised = TRUE;\n\n"]),
+ mlds_output_calls_to_register_tci(ModuleName,
+ TypeCtorInfoDefns)
+ ;
+ []
+ ),
+ io__write_string("}\n\n"),
output_init_fn_name(ModuleName, "_debugger"),
io__write_string("\n{\n"),
io__write_string(
"\tMR_fatal_error(""debugger initialization in MLDS grade"");\n"),
- io__write_string("\n}\n").
+ io__write_string("}\n").
:- pred output_init_fn_name(mlds_module_name::in, string::in,
io__state::di, io__state::uo) is det.
@@ -391,43 +426,45 @@
io__write_string(Suffix),
io__write_string("(void)").
-:- pred mlds_output_init_main_fn(mlds_module_name::in, mlds__defns::in,
+:- pred need_to_init_entries(globals::in) is semidet.
+need_to_init_entries(Globals) :-
+ % We only need to output calls to MR_init_entry() if profiling is
+ % enabled. (It would be OK to output the calls regardless, since
+ % they will macro-expand to nothing if profiling is not enabled,
+ % but for readability of the generated code we prefer not to.)
+ ( Option = profile_calls
+ ; Option = profile_time
+ ; Option = profile_memory
+ ),
+ globals__lookup_bool_option(Globals, Option, yes).
+
+ % Generate calls to MR_init_entry() for the specified functions.
+ %
+:- pred mlds_output_calls_to_init_entry(mlds_module_name::in, mlds__defns::in,
io__state::di, io__state::uo) is det.
-mlds_output_init_main_fn(_ModuleName, []) --> [].
-mlds_output_init_main_fn(ModuleName, [Defn | Defns]) -->
- { Defn = mlds__defn(EntityName, _Context, _Flags, _EntityDefn) },
- (
- { EntityName = mlds__function(_, _, _, _) }
- ->
- { QualName = qual(ModuleName, EntityName) },
- io__write_string("\tMR_init_entry("),
- mlds_output_fully_qualified_name(QualName),
- io__write_string(");\n")
- ;
- []
- ),
- mlds_output_init_main_fn(ModuleName, Defns).
+mlds_output_calls_to_init_entry(_ModuleName, []) --> [].
+mlds_output_calls_to_init_entry(ModuleName, [FuncDefn | FuncDefns]) -->
+ { FuncDefn = mlds__defn(EntityName, _, _, _) },
+ io__write_string("\tMR_init_entry("),
+ mlds_output_fully_qualified_name(qual(ModuleName, EntityName)),
+ io__write_string(");\n"),
+ mlds_output_calls_to_init_entry(ModuleName, FuncDefns).
-:- pred mlds_output_init_type_table_fn(mlds_module_name::in, mlds__defns::in,
+ % Generate calls to MR_register_type_ctor_info() for the specified
+ % type_ctor_infos.
+ %
+:- pred mlds_output_calls_to_register_tci(mlds_module_name::in, mlds__defns::in,
io__state::di, io__state::uo) is det.
-mlds_output_init_type_table_fn(_ModuleName, []) --> [].
-mlds_output_init_type_table_fn(ModuleName, [Defn | Defns]) -->
- { Defn = mlds__defn(EntityName, _Context, _Flags, EntityDefn) },
- (
- { EntityDefn = mlds__data(Type, _) },
- { Type = mlds__rtti_type(RttiName) },
- { RttiName = type_ctor_info }
- ->
- { QualName = qual(ModuleName, EntityName) },
- io__write_string("\tMR_register_type_ctor_info(&"),
- mlds_output_fully_qualified_name(QualName),
- io__write_string(");\n")
- ;
- []
- ),
- mlds_output_init_type_table_fn(ModuleName, Defns).
+mlds_output_calls_to_register_tci(_ModuleName, []) --> [].
+mlds_output_calls_to_register_tci(ModuleName,
+ [TypeCtorInfoDefn | TypeCtorInfoDefns]) -->
+ { TypeCtorInfoDefn = mlds__defn(EntityName, _, _, _) },
+ io__write_string("\tMR_register_type_ctor_info(&"),
+ mlds_output_fully_qualified_name(qual(ModuleName, EntityName)),
+ io__write_string(");\n"),
+ mlds_output_calls_to_register_tci(ModuleName, TypeCtorInfoDefns).
%-----------------------------------------------------------------------------%
%
Index: runtime/mercury_conf_param.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_conf_param.h,v
retrieving revision 1.40
diff -u -d -r1.40 mercury_conf_param.h
--- runtime/mercury_conf_param.h 2000/11/07 08:58:33 1.40
+++ runtime/mercury_conf_param.h 2000/11/08 08:18:09
@@ -252,6 +252,13 @@
** (this also means the initialization code needs
** to be run some time before the first use of the
** label table).
+**
+** Note that for the MLDS back-end, the calls to MR_init_entry()
+** that insert the function addresses in the label table are only
+** output if the right compiler options are enabled. So if you change
+** the condition of this `#ifdef', and you want your changes to apply
+** to the MLDS back-end too, you may also need to change the
+** `need_to_init_entries' predicate in compiler/mlds_to_c.m.
*/
#ifdef MR_INSERT_LABELS
Index: runtime/mercury_goto.h
===================================================================
RCS file: /home/mercury1/repository/mercury/runtime/mercury_goto.h,v
retrieving revision 1.24
diff -u -d -r1.24 mercury_goto.h
--- runtime/mercury_goto.h 2000/10/09 02:07:51 1.24
+++ runtime/mercury_goto.h 2000/11/08 08:18:29
@@ -82,6 +82,14 @@
#define make_local(n, a, l) /* nothing */
#endif
+/*
+** Note that for the MLDS back-end, the calls to MR_init_entry(),
+** which eventually expand to make_entry(), are only output if
+** the right compiler options are enabled. So if you change the
+** condition of this `#ifdef', and you want your changes to apply
+** to the MLDS back-end too, you may also need to change the
+** `need_to_init_entries' predicate in compiler/mlds_to_c.m.
+*/
#if defined(MR_INSERT_LABELS) || defined(PROFILE_CALLS)
#define make_entry(n, a, l) make_entry_ai(n, a, l)
#else
--
Fergus Henderson <fjh at cs.mu.oz.au> | "I have always known that the pursuit
| of excellence is a lethal habit"
WWW: <http://www.cs.mu.oz.au/~fjh> | -- the last words of T. S. Garp.
--------------------------------------------------------------------------
mercury-developers mailing list
Post messages to: mercury-developers at cs.mu.oz.au
Administrative Queries: owner-mercury-developers at cs.mu.oz.au
Subscriptions: mercury-developers-request at cs.mu.oz.au
--------------------------------------------------------------------------
More information about the developers
mailing list