Allow dumping of nested functions in MLDS code.

compiler/mlds_to_c_util.m:
    Add a flag to the structure that is threaded through all the other
    mlds_to_c_*.m modules that says whether we are generating C target code
    or an MLDS dump.

compiler/mlds_to_c_stmt.m:
    If we are generating target code, continue to insist on the absence
    of nested functions. However, when generating an MLDS dump, allow them
    and print them out. This is needed to avoid compiler aborts when
    generating MLDS dumps for e.g. tests/hard_coded/space.m.

compiler/mlds_to_c_file.m:
    Tell mlds_to_c_util.m: target code or MLDS dump.

compiler/mercury_compile_mlds_back_end.m:
    Tell mlds_to_c_file.m: target code or MLDS dump.
This commit is contained in:
Zoltan Somogyi
2019-05-19 14:38:20 +02:00
parent 9867404681
commit 93dc7b010d
4 changed files with 52 additions and 18 deletions

View File

@@ -67,6 +67,7 @@
:- import_module ml_backend.ml_elim_nested. % MLDS -> MLDS
:- import_module ml_backend.ml_optimize. % MLDS -> MLDS
:- import_module ml_backend.mlds_to_c_file. % MLDS -> C
:- import_module ml_backend.mlds_to_c_util.
:- import_module ml_backend.mlds_to_java_file. % MLDS -> Java
:- import_module ml_backend.mlds_to_cs_file. % MLDS -> C#
:- import_module parse_tree.file_names.
@@ -359,7 +360,7 @@ mlds_to_high_level_c(Globals, MLDS, Succeeded, !IO) :-
globals.lookup_bool_option(Globals, statistics, Stats),
maybe_write_string(Verbose, "% Converting MLDS to C...\n", !IO),
output_c_mlds(MLDS, Globals, "", Succeeded, !IO),
output_c_mlds(MLDS, Globals, tod_target, "", Succeeded, !IO),
maybe_write_string(Verbose, "% Finished converting MLDS to C.\n", !IO),
maybe_report_stats(Stats, !IO).
@@ -407,10 +408,11 @@ maybe_dump_mlds(Globals, MLDS, StageNum, StageName, !IO) :-
DumpSuffix = "_dump." ++ StageNumStr ++ "-" ++ StageName,
(
DumpPredNames = [],
output_c_mlds(MLDS, Globals, DumpSuffix, _Succeeded, !IO)
output_c_mlds(MLDS, Globals, tod_dump, DumpSuffix, _Succeeded, !IO)
;
DumpPredNames = [_ | _],
output_c_dump_preds(MLDS, Globals, DumpSuffix, DumpPredNames, !IO)
output_c_dump_preds(MLDS, Globals, tod_dump, DumpSuffix,
DumpPredNames, !IO)
),
maybe_write_string(Verbose, "% done.\n", !IO)
else

View File

@@ -31,6 +31,7 @@
:- import_module libs.
:- import_module libs.globals.
:- import_module ml_backend.mlds.
:- import_module ml_backend.mlds_to_c_util.
:- import_module bool.
:- import_module io.
@@ -38,7 +39,7 @@
%---------------------------------------------------------------------------%
% output_c_mlds(MLDS, Globals, Suffix, Succeeded, !IO):
% output_c_mlds(MLDS, Globals, TargetOrDump, Suffix, Succeeded, !IO):
%
% Output C code to the appropriate C file and C declarations to the
% appropriate header file. The file names are determined by the module
@@ -46,17 +47,17 @@
% for debugging dumps. For normal output, the suffix should be the empty
% string.)
%
:- pred output_c_mlds(mlds::in, globals::in, string::in, bool::out,
io::di, io::uo) is det.
:- pred output_c_mlds(mlds::in, globals::in, target_or_dump::in,
string::in, bool::out, io::di, io::uo) is det.
% output_c_dump_preds(MLDS, Globals, Suffix, DumpPreds, !IO):
% output_c_dump_preds(MLDS, Globals, TargetOrDump, Suffix, DumpPreds, !IO):
%
% Output C code for the predicates and/or functions whose names
% occurs in DumpPreds. The file name to write to is determined similarly
% to how output_c_mlds does it, but with ".mlds_dump" replacing ".c".
%
:- pred output_c_dump_preds(mlds::in, globals::in, string::in,
list(string)::in, io::di, io::uo) is det.
:- pred output_c_dump_preds(mlds::in, globals::in, target_or_dump::in,
string::in, list(string)::in, io::di, io::uo) is det.
:- pred func_defn_has_name_in_list(list(string)::in, mlds_function_defn::in)
is semidet.
@@ -85,7 +86,6 @@
:- import_module ml_backend.mlds_to_c_func.
:- import_module ml_backend.mlds_to_c_global.
:- import_module ml_backend.mlds_to_c_name.
:- import_module ml_backend.mlds_to_c_util.
:- import_module ml_backend.mlds_to_target_util.
:- import_module parse_tree.
:- import_module parse_tree.file_names.
@@ -105,7 +105,7 @@
:- import_module string.
:- import_module term.
output_c_mlds(MLDS, Globals, Suffix, Succeeded, !IO) :-
output_c_mlds(MLDS, Globals, TargetOrDump, Suffix, Succeeded, !IO) :-
% We output the source file before we output the header.
% The reason why we need this order is that the mmake dependencies
% we generate say that the header file depends on the source file.
@@ -117,7 +117,7 @@ output_c_mlds(MLDS, Globals, Suffix, Succeeded, !IO) :-
%
ModuleName = mlds_get_module_name(MLDS),
module_source_filename(Globals, ModuleName, SourceFileName, !IO),
Opts = init_mlds_to_c_opts(Globals, SourceFileName),
Opts = init_mlds_to_c_opts(Globals, SourceFileName, TargetOrDump),
output_c_file_opts(MLDS, Opts, Suffix, Succeeded0, !IO),
(
Succeeded0 = yes,
@@ -171,10 +171,10 @@ output_c_header_file_opts(MLDS, Opts, Suffix, Succeeded, !IO) :-
%---------------------------------------------------------------------------%
output_c_dump_preds(MLDS, Globals, Suffix, DumpPredNames, !IO) :-
output_c_dump_preds(MLDS, Globals, TargetOrDump, Suffix, DumpPredNames, !IO) :-
ModuleName = mlds_get_module_name(MLDS),
module_source_filename(Globals, ModuleName, SourceFileName, !IO),
Opts = init_mlds_to_c_opts(Globals, SourceFileName),
Opts = init_mlds_to_c_opts(Globals, SourceFileName, TargetOrDump),
module_name_to_file_name(Globals, do_create_dirs, ".mlds_dump" ++ Suffix,
ModuleName, DumpFileName, !IO),
MLDS_ModuleName = mercury_module_name_to_mlds(ModuleName),

View File

@@ -55,6 +55,7 @@
:- import_module mdbcomp.
:- import_module mdbcomp.sym_name.
:- import_module ml_backend.mlds_to_c_data.
:- import_module ml_backend.mlds_to_c_func.
:- import_module ml_backend.mlds_to_c_name.
:- import_module ml_backend.mlds_to_c_type.
:- import_module parse_tree.prog_foreign.
@@ -138,9 +139,22 @@ mlds_output_stmt_block(Opts, Indent, FuncInfo, Stmt, !IO) :-
% Output forward declarations for any nested functions defined in
% this block, in case they are referenced before they are defined.
%
% We do not support high level C code grades with nested functions,
% but we *do* generate nested functions internally that we later
% flatten out. Until we step away from generating nested functions
% entirely, we will need to be print out C code with nested functions
% for MLDS dumps.
FuncInfo = func_info_c(FuncName, _),
FuncName = qual_function_name(ModuleName, _),
(
FuncDefns = [_ | _],
unexpected($pred, "FuncDefns != []")
expect(unify(Opts ^ m2co_target_or_dump, tod_dump), $pred,
"nested functions in target C code"),
list.foldl(
mlds_output_function_decl_opts(Opts, BlockIndent, ModuleName),
FuncDefns, !IO),
io.write_string("\n", !IO)
;
FuncDefns = []
),
@@ -151,6 +165,14 @@ mlds_output_stmt_block(Opts, Indent, FuncInfo, Stmt, !IO) :-
;
LocalVarDefns = []
),
(
FuncDefns = [_ | _],
mlds_output_function_defns(Opts, BlockIndent, ModuleName,
FuncDefns, !IO),
io.write_string("\n", !IO)
;
FuncDefns = []
),
mlds_output_statements(Opts, BlockIndent, FuncInfo, SubStmts, !IO),
c_output_context(Opts ^ m2co_line_numbers, Context, !IO),
output_n_indents(BraceIndent, !IO),

View File

@@ -44,6 +44,10 @@
% since they will macro-expand to nothing if profiling is not enabled,
% but for readability of the generated code we prefer not to.)
%
% m2co_target_or_dump says whether we are generating target cod
% or an MLDS dump. We permit nested functions in MLDS code only
% when printing MLDS dumps, not when generating target code.
%
% m2co_std_func_decl is `yes' if want to use standard argument names
% in function declarations.
%
@@ -67,12 +71,18 @@
m2co_target :: compilation_target,
m2co_gc_method :: gc_method,
m2co_target_or_dump :: target_or_dump,
m2co_std_func_decl :: bool,
m2co_break_context :: break_context
).
:- func init_mlds_to_c_opts(globals, string) = mlds_to_c_opts.
:- type target_or_dump
---> tod_target
; tod_dump.
:- func init_mlds_to_c_opts(globals, string, target_or_dump) = mlds_to_c_opts.
%---------------------------------------------------------------------------%
@@ -103,7 +113,7 @@
%---------------------------------------------------------------------------%
init_mlds_to_c_opts(Globals, SourceFileName) = Opts :-
init_mlds_to_c_opts(Globals, SourceFileName, TargetOrDump) = Opts :-
globals.lookup_bool_option(Globals, line_numbers, LineNumbers),
globals.lookup_bool_option(Globals, line_numbers_around_foreign_code,
ForeignLineNumbers),
@@ -130,7 +140,7 @@ init_mlds_to_c_opts(Globals, SourceFileName) = Opts :-
Opts = mlds_to_c_opts(Globals, SourceFileName,
LineNumbers, ForeignLineNumbers, Comments, HighLevelData,
SinglePrecFloat, ProfileCalls, ProfileMemory, ProfileTime, NeedToInit,
Target, GCMethod, StdFuncDecls, BreakContext).
Target, GCMethod, TargetOrDump, StdFuncDecls, BreakContext).
%---------------------------------------------------------------------------%
%