mirror of
https://github.com/Mercury-Language/mercury.git
synced 2025-12-15 13:55:07 +00:00
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:
@@ -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
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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).
|
||||
|
||||
%---------------------------------------------------------------------------%
|
||||
%
|
||||
|
||||
Reference in New Issue
Block a user