compiler/add_pragma.m:
The status checks in this module used to check for only one
of the four possible combinations of <is pragma exported, is the
pred the pragma is for expored>, even though we may want to generate
errors or warnings in three of those combinations. Fix this.
If an ambiguous pragma applies to more than one predicate, handle
the status checks of each separately.
When adding fact table pragmas to the HLDS, replace several lines
of code that reuse an existing largish predicate with the single line
of code from that predicate that we actually need.
Stop representing the statuses of pragmas using the pred_status type,
since the item_mercury_status that all items come with is adequate
for all our needs, and is impossible to confuse with the status
of the pred_info they refer to.
library/exception.m:
library/require.m:
Move termination pragmas for exported predicates and functions
from the implementation section to the interface section. This
avoids a warning that we now generate in such situations.
tests/term/exception_analysis_test.trans_opt_exp:
tests/term/exception_analysis_test2.trans_opt_exp:
Expected improved termination analysis results now that we export
termination pragmas that used to be kept private.
tests/warnings/foreign_term_invalid.{m,exp}:
Avoid warnings about keeping decl pragmas about exported predicates
private by moving them into the interface.
Fix the formatting of the top-of-module comment.
Expect updated line numbers.
tests/warnings/pragma_term_conflict.{m,exp}:
Don't avoid a warning about keeping decl pragmas about exported predicates
private. Instead, document it as an additional purpose of this test.
Expect both the extra warning and updated line numbers.
tests/invalid/pragma_export.{m,err_exp}:
A new test case for testing the error message for inappropriately
exported pragmas.
tests/invalid/Mmakefile:
Enable the new test case.
compiler/intermod.m:
We used to put predicate declarations and definitions into .opt files
in order of pred_id. Since pred_ids are allocated sequentially, this
meant that the order of the pragmas in .*opt files recording analysis
results was determined by the order of the predicate declarations
in the .m file, and if this changes, everything that depends on the
.opt file has to be recompiled. Change this to put the pragmas into
an order based on the predicates' names, arities, and pred_or_func flag.
Precede each block of analysis results (one block per pragma type)
with a blank line, to make .*opt files a bit easier to read by revealing
their structure.
When printing analysis results for all the procedures of a predicate,
don't get a list of proc_ids and then look them up one by one; just
iterated over all the proc_infos in the proc_table.
Rename some predicates to make their names fit into the naming scheme
used in the rest of the module.
compiler/hlds_module.m:
compiler/hlds_pred.m:
The results of the exception, trailing and mm_tabling analyses
used to be stored in the module_info as maps from pred_proc_ids
to the results about the procedure. Change this to store them
in the proc_info of the procedure, since any code that looks up
the results of an analysis typically also wants to look up other
information in the proc_info as well. (intermod.m certainly does.)
The results of the termination, structure sharing and structure reuse
analysis were already stored in the proc_info.
compiler/add_pragma.m:
When reading in exceptions, trailing and mm_tabling pragmas,
add their information to the named procedure's proc_info,
not to a map in the module_info.
compiler/exception_analysis.m:
compiler/tabling_analysis.m:
compiler/trailing_analysis.m:
Put analysis results into procedures' proc_infos, not into a map
in the module_info, and if need be, look it up there as well.
compiler/goal_form.m:
Look up the results of exception_analysis in procedures' proc_infos,
not in a map in the module_info.
compiler/lco.m:
Work around a bug in lco.m itself exposed by the move of analysis
results to proc_infos. When lco.m duplicates the proc_info of a procedure
that it optimizes, it now duplicates its analysis results as well.
The duplication is correct in a sense, since any results of the exception,
trailing and mm_tabling analysis that hold for the original procedure
have to hold for the duplicate copy as well, but interestingly, this extra
precision causes simplify to believe that the call from the original
procedure to duplicated procedure is dead code that can be eliminated,
since it is det and appears to have no outputs. In fact, it does have
outputs, but it returns those outputs via impure calls to store_at_ref.
While the call to store_at_ref in the duplicated procedure is marked
as impure, the call to the duplicate procedure in the original procedure
is NOT (yet) so marked.
compiler/parse_tree_out_pred_decl.m:
When printing parts of predicate declarations, e.g. as parts of pragmas
that record analysis results, don't take as an argument a context that
will never be used.
compiler/add_clause.m:
compiler/dependency_graph.m:
compiler/hlds_out_pred.m:
compiler/make_hlds_error.m:
compiler/mode_errors.m:
compiler/parse_tree_out.m:
compiler/parse_tree_out_pragma.m:
compiler/typecheck.m:
Conform to the changes in parse_tree_out_pred_decl.m above.
tests/term/*.trans_opt_exp:
Expect the same termination analysis results as before, just in
predicate name order, and with a blank line before each block.
Estimated hours taken: 0.1
Branches: main
tests/term/*.trans_opt_exp:
Update the expected outputs of these test cases.
These have changed because of the recent change
to termination2_info pragmas.
Estimated hours taken: 1
Branches: main
Enable the support for writing out termination2_info pragmas
in the .opt and .trans_opt files.
Test both termination analyses when running the test suite.
compiler/term_constr_main.m:
compiler/trans_opt.m:
Uncomment the code that causes termination2_info pragmas
to be written out the .opt and .trans_opt files.
tests/term/Mmakefile:
Run the new termination analyser on these tests as well.
tests/term/*.trans_opt_exp:
Include the expected termination2_info pragmas.
Estimated hours taken: 70
Branches: main
Add an analysis that tries to identify those procedures
in a module that will not throw an exception.
(I guess it may be more accurate to call it a non-exception analysis).
For those procedures that might throw exceptions the
analysis further tries to distinguish between those
that throw an exception as a result of a call to throw
and those that throw an exception as a result of a
call to a unification/comparison predicate that may involve
calls to user-defined equality/comparison predicates that throw
exceptions.
This sort of thing used to be done by the termination analysis,
where being able to prove termination was equated with not
throwing an exception. This no longer works now that
the termination analyser considers exception.throw/1 to
be terminating - and in fact it never quite worked anyway
because the termination analyser was not handling things
like foreign code and user-defined equality and comparison
predicates correctly.
There are currently a few limitations, the main ones being:
* we currently use transitive-intermodule optimization rather
than the intermodule-analysis framework. This may causes
problems when their are cycles in the module dependency graph.
* we currently assume that all calls to higher-order predicates
may result in an exception being thrown.
* we currently assume that all foreign procs that make calls
back to Mercury may throw exceptions.
* we currently assume that all solver types and existentially
quantified types might result in an exception being thrown.
It should be possible to remove these limitations in later
versions.
This diff also modifies the cannot_loop_or_throw family of
predicates in goal_form.m. There are now two versions of each
predicate; one that can make use of information from the
termination and exception analyses and one that cannot.
compiler/exception_analysis.m:
The new analysis.
compiler/prog_data.m:
compiler/prog_io_pragma.m:
Handle `:- pragma exceptions(...' in .opt and .trans_opt files.
compiler/hlds_module.m:
Attach information to each module about whether each procedure
in the module may throw an exception.
compiler/goal_form.m:
Rewrite the predicates in this module so that they can
optionally use information from the exception analysis.
compiler/constraint.m:
compiler/goal_util.m:
compiler/rl.m:
compiler/simplify.m:
Use information from exception and termination analyses
when performing various optimizations.
compiler/type_util.m:
Add a new predicate type_util.type_is_existq/2 that tests
whether a type is existentially quantified or not.
compiler/mercury_compile.m:
compiler/mercury_to_mercury.m:
compiler/modules.m:
compiler/options.m:
compiler/module_qual.m:
compiler/make_hlds.m:
compiler/recompilation.version.m:
compiler/trans_opt.m:
compiler/transform_hlds.m:
Minor changes needed by the above.
NEWS:
compiler/notes/compiler_design.html:
doc/user_guide.texi:
Mention the new analysis.
tests/README:
Include a description of the term directory.
tests/term/Mercury.options:
tests/term/Mmakefile:
tests/term/exception_analysis_test.m:
tests/term/exception_analysis_test.trans_opt_exp:
Add a test for the new analysis.