Commit Graph

8 Commits

Author SHA1 Message Date
Zoltan Somogyi
8f50e16eb2 Fix a possible silent failure when making .int files.
When I split two files in a recent change, I ran into an annoying problem.
The problem was caused by unneeded imports in the interface of the new modules,
whose initial part I originally simply copied from the source module.
The problem was that when I attempted to compile new module A which imported
new module B, the compilation of module A would fail with a message about
not finding module B's .int file. It couldn't find B.int because the
compiler invocation that was supposed to create it failed, but it did not
print any error message about *why* it failed, and as a consequence,
it also did not set the exit status to nonzero to tell mmake that
the file was not actually built, so later build actions that need that file
should not be executed.

The cause of this problem was the following.

- The default value of the --warn-unused-imports is off, but COMP_FLAGS
  turns it on for modules in the compiler directory. This enables warnings
  generated by unused_imports.m.

- There is code that does a similar job in module_qual.qual_errors.m, but
  that one is limited to imports in interface sections. Due to the overlap
  between tasks, when this code finds an unused import_module declaration
  in an interface, it generates an error message that was conditional
  on --warn-unused-imports being off. When it was on, as it is with
  COMP_FLAGS, it generates an error_spec that, when given to write_error_specs,
  generates no output.

- Code in write_module_interface_files.m that decided whether the building
  of the .int file has failed, tested only whether the process of generating
  its contents has returned any error_specs, not whether it returned
  any error_specs that would actually be printed, and, by being printed
  with a sufficiently high severity, would set the exit status to signal
  failure.

compiler/error_util.m:
    The two changes to this file together fix the root cause of this problem.

    First, a new predicate checks whether an error_spec has any part
    whose printing is NOT disabled by being attached to an unmet condition.

    Second, the predicate through which we pass all error_specs created
    during the generation of the contents of the .int file filters out
    any error_specs that yield no output.

The later changes are not strictly part of the bugfix, they are there
simply to make the code simpler to understand, in the hope that this fact
will reduce the probability of similar problems in the future.

compiler/module_qual.qual_errors.m:
    Instead of generating error_specs that are conditional on
    --warn-unused-imports being OFF, generate them conditional on
    the new option --warn-unused-interface-imports being ON.
    Using --warn-unused-imports here was strange because that option controls
    whether the compiler invokes unused_imports.m. It was NOT specific
    to this piece of code, while the new option is.

compiler/options.m:
doc/user_guide.texi:
    Add the new option. Comment out its documentation, since I don't think
    I can describe the reason for its existence simply enough for users
    to understand.

compiler/handle_options.m:
    Turn off the new option --warn-unused-interface-imports if
    --warn-unused-imports is set. This duplicates the old behavior
    of module_qual.qual_errors.m.

    Turn off the new option --warn-unused-interface-imports if
    we are generating interface files. This is because the presence
    of unneeded imports in .m files does not prevent the creation
    of valid .int files, so having to fix such warnings at .int file
    creation time interferes with the programmer's ability to choose
    the order in which he/she works on getting modules to a compilable shape.

compiler/write_module_interface_files.m:
    Generate all output on error as part of an error_spec.

compiler/unused_imports.m:
    Fix indentation.

tests/valid_make_int/extra_interface_import.m:
    A new test case for this bug.

tests/valid_make_int/Mmakefile:
    Enable the new test case.
2021-12-17 12:55:29 +11:00
Zoltan Somogyi
8827b6a466 Make --halt-at-invalid-interface the default.
NEWS:
    Mention this fact.

    Group related changes together.

    Fix some typos.

compiler/error_util.m:
    Let the halt_at_invalid_interface option govern whether we print error
    messages when we generate .int/.int2 files, rather than
    the print_errors_warnings_when_generating_interface option.
    This simplifies the use of that option.

compiler/options.m:
doc/user_guide.texi:
    Document the halt_at_invalid_interface option.

    Delete the print_errors_warnings_when_generating_interface option,
    since its functionality has been subsumed into halt_at_invalid_interface.

compiler/grab_modules.m:
    Check the accessibility of imported modules not just when generating target
    language code, but also when generating .int/.int2 files. Without this,
    the test_nested test case, which this diff moves from invalid to
    invalid_make_int, would miss out on some errors being reported
    in its new home.

    To make the above possible, refactor the code that does the check
    to let it work on aug_make_int_units as well as from aug_compilation_units.
    Make the wording of any error message depend on where the info came from,
    because unlike aug_comp_units, aug_make_int_units work with an
    known-incomplete picture of the relevant info.

    Update some obsolete comments.

compiler/write_module_interface_files.m:
    Add a comment about a design decision that affects this diff.

tests/invalid_make_int/Mercury.options:
tests/invalid_make_int/Mmakefile:
    Add to this directory's list the test cases that this diff moves
    to this directory from other test directories, because the errors
    that they test for are now reported at interface generation time.

    Fix the rule handling multimodule tests, now that we have some :-(

    Specify -j1 for this directory, since the two tests moved here
    from invalid_submodules include nested submodules.

tests/invalid_make_int/bad_type_class_constraint_intermodule.{m,int_err_exp}:
    Move this test case here from invalid, renaming files slightly,
    and update the expected output.

tests/invalid_make_int/bug499.{m,int_err_exp}:
    Move this test case here from invalid, and update the expected output.

tests/invalid_make_int/int_impl_imports.{m,int_err_exp}:
tests/invalid_make_int/int_impl_imports_2.m:
    Move this test case here from invalid, and update the expected output.

tests/invalid_make_int/missing_interface_import2.{m,int_err_exp}:
tests/invalid_make_int/missing_interface_import3.m:
    Move this test case here from invalid, and update the expected output.

tests/invalid_make_int/missing_parent_import.{m,int_err_exp}:
tests/invalid_make_int/children.m:
tests/invalid_make_int/children2.m:
    Move this test case here from invalid_submodules,
    and update the expected output.

tests/invalid_make_int/sub_c.{m,int_err_exp}:
tests/invalid_make_int/sub_a.m:
    Move this test case here from invalid_submodules,
    and update the expected output.

tests/invalid_make_int/test_nested.{m,int_err_exp}:
tests/invalid_make_int/parent.m:
tests/invalid_make_int/parent.private_child.m:
tests/invalid_make_int/parent.public_child.m:
tests/invalid_make_int/parent.undeclared_child.m:
tests/invalid_make_int/parent2.child.m:
tests/invalid_make_int/parent2.m:
    Move this test case here from invalid, and update the expected output.

tests/invalid_make_int/transitive_import.{m,int_err_exp}:
    Move this test case here from invalid, update it,
    and update the expected output.

tests/invalid/Mmakefile:
    Delete from the list of tests in this directory the tests
    moved to invalid_make_int, and test bug521.

tests/invalid/bug521.{m,err_exp}:
tests/invalid/bug521_sub.m:
    Delete this test. invalid_make_int already had a copy of the relevant
    part of this test.

tests/invalid_submodules/Mmakefile:
    Delete from the list of tests in this directory the two tests
    moved to invalid_make_int.

    Delete from the list of tests in this directory two other tests
    for which we now detect some or all of the errors tested for
    at interface generation time, but which are already covered
    by other tests.

tests/valid_make_int/Mmakefile:
    Delete from the list of tests in this directory the test
    moved to invalid_make_int. (We could successfully generate
    a .int file for that test case *only if* we did not check it
    for errors :-)

tests/valid_seq/intermod_nested_module_bug2.m:
tests/valid_seq/intermod_nested_module_bug2.sub.m:
    Move two module imports from the parent to the child module,
    because only the child needs them, and any compiler with this diff
    will now complain about them being unused in the parent
    at interface generation time. Delete a third import, which was
    not used anywhere.
2021-11-20 23:49:19 +11:00
Zoltan Somogyi
1f45f91886 Make "mmake runtests" work again.
My commit afe2887882 broke the ability
to run the test suite outside of a bootcheck by executing "mmake runtests"
in the tests directory. This diff fixes that.

tests/Mmake.common:
    Don't define "TESTS_DIR = ..". While every single tests/*/Mmakefile
    defined it as such, I overlooked the fact that tests/Mmakefile itself
    defined it ".", referring to the same directory from a different starting
    point. Document this easily-overlooked fact.

    Rename the old runtests target, which after afe2887 runs the tests
    in a single directory, as runtests_dir, to leave the target name
    "runtests" itself free for tests/Mmakefile to use.

tests/Mmakefile:
    Define "TESTS_DIR = .", and add a target "runtests" which invokes
    "mmake runtests_dir" in each test directory.

tools/bootcheck:
    Invoke "mmake runtests_dir" instead of "mmake runtests" in each
    test directory.

    Initialize a variable just before it is used.

tests/*/Mmakefile:
    Add back the definition "TESTS_DIR = .."
2020-06-10 01:05:15 +10:00
Zoltan Somogyi
9cbe5d2caf Put type_repn items for complex types into .int files.
compiler/decide_type_repn.m:
    Previously, this module computed type_repn items to put into .int3 files
    for a subset of the type constructors defined in the current module:
    the direct_dummy, enum and notag types (the *simple* types),
    and the du types whose representation is guaranteed to be
    a word-aligned pointer when targeting C. (We care about pointers
    being word-aligned only when applying the direct arg optimization.
    This optimization is applicable only with the low level data
    representation, which we use only when targeting C.)

    This diff adds code to decide the representations of *all* the
    type constructors defined in the current module.

    This code is based on the existing code in du_type_layout.m,
    which it is intended to eventually replace, but its job is more general,
    because it decides the representation of each type not just for
    one platform (the one we want to generate code), but for all possible
    platforms. This is because we want to put the descriptions of type
    representations into the module's .int file to serve as a single source
    of truth for all modules that use the types defined in this module,
    and the contents of .int files should be platform-independent.
    For our purposes, there are six kinds of platforms, which are
    distinguished along three axes: 64 vs 32 bit machines, spf vs non-spf
    grades, and direct arg optimization enabled vs disabled. That is eight
    combinations, but on 64 bit machines, a float takes up one word whether
    that float is single or double precision, so two combinations aren't valid.

    Some of the change to this module consists of generalizing the existing
    code so that it can decide simple types not just when targeting .int3 files
    but .int files as well. However, the bulk of it is code for deciding
    the representations of non-simple types. The code is not lifted straight
    from du_type_layout.m. There are two main kinds of changes.

    First, I took the opportunity to simplify the algorithms used.
    For example, while du_type_layout.m passes over each function symbol
    in the most general kind of type twice: once to assign it a cons_tag,
    and once to decide how to pack its arguments, the code here does both jobs
    in one pass. Another example is that for historical reasons,
    du_type_layout.m computed the amount of space needed for an argument
    in one place for sub-word-sized arguments, and in another place
    for more-than-word-sized arguments; decide_type_repn.m does it all
    in one place.

    Second, since we compute a representation for each type six times,
    I tried to avoid obvious inefficiencies, but only if the code
    remained simple. In the future, we may want to use an approach
    based on the idea that in the process of computing the first
    representation, we look out for any indication that the representation
    may be different on any of the other five platforms, and if not,
    we just reuse the first representation on the other five platforms as well.
    However, that would be appropriate only *after* we have a simpler
    system that has proven to work in practice.

    There is a third, smaller change: when deciding whether an argument
    is packable, we take into account not just equivalence type
    definitions, but the definitions of notag types as well.
    This takes advantage of the fact that if a notag type is abstract
    exported, its representation is put into the relevant .int3 file
    even though its definition isn't. (This is why du_type_layout.m
    couldn't "see through" notag types: it couldn't depend on knowing
    which types were notags.)

compiler/prog_item.m:
    Change the types we use for type representation information.
    Their previous definitions baked in the assumption that the only
    distinction between platforms that mattered was the 64 vs 32 bit
    distinction, which is not the case.

    Use a more consistent naming scheme for the types we use
    to represent type representation information.

    Include the "dereferenced" types of the arguments in functors'
    representations. (I use "dereferencing" here to mean expanding
    equivalence types and throwing away any notag wrappers.).
    We don't need it when generating C code using the low level
    data representation, but we do need it to create constructors
    when generating e.g. Java code that uses the high level data
    representation.

compiler/parse_type_repn.m:
    Rewrite most of this module due to the changes in prog_item.m.

compiler/parse_tree_out_type_repn.m:
    A new module containing the code for writing out type representations.
    The original code used to be in parse_tree_out.m, but it has been
    mostly rewritten. Partly this is due the changes in prog_item.m,
    but partly it is to provide much more structured output for humans,
    since this makes debugging so much easier.

compiler/parse_tree.m:
    Add the new module to the parse_tree package.

compiler/parse_tree_out.m:
    Delete the code moved to parse_tree_out_type_repn.m.

compiler/parse_tree_out_info.m:
    Provide a mechanism for selecting between output for machines
    (the default) and output for humans.

compiler/hlds_data.m:
compiler/prog_data.m:
    Move the ptag type from hlds_data.m to prog_data.m, to make it
    accessible in prog_item.m.

    Add some documentation in prog_data.m.

compiler/comp_unit_interface.m:
    If the experiment1 option is enabled, invoke decide_type_repn.m
    to decide what type_repn items to put into the .int file we are
    generating. Otherwise, maintain the status quo.

compiler/write_module_interface_files.m:
    Pass the globals to comp_unit_interface.m so it can look up experiment1.

compiler/equiv_type.m:
    Add a predicate for expanding equivalence types for use by
    decide_type_repn.m. This predicate expands just one type,
    but reports any use of circular equivalence types in that type.

    Improve the error message for circular equivalence types by *naming*
    the type constructors involved. To make this possible, pass around
    sets of such type constructors instead of just a boolean saying
    *whether* we have found *some* circular equivalence type.

    Replace bools used as changed/unchanged flag with a bespoke type.

    Standardize some variable names.

compiler/options.m:
    Add the developer-only option --pack-everything, which, if set,
    tells decide_type_repn.m to turn on all the packing options
    that currently work. This is to allow the testing of decide_type_repn.m
    in the eventual intended mode of operation, even if the various
    allow-packing-... options used by du_type_layout.m are set to "no".

compiler/disj_gen.m:
compiler/equiv_type_hlds.m:
compiler/llds_out_data.m:
compiler/lookup_util.m:
compiler/ml_call_gen.m:
compiler/ml_closure_gen.m:
compiler/mlds_to_c_data.m:
compiler/rtti.m:
compiler/rtti_out.m:
compiler/rtti_to_mlds.m:
compiler/tag_switch.m:
    Conform to the changes above (mostly the move of ptag to prog_data.m.)

compiler/parse_pragma.m:
    Improve indentation.

tests/valid_make_int/test_repn.m:
tests/valid_make_int/test_repn_sub.m:
    A fairly comprehensive test case of the new functionality.
    test_repn_sub.m defines one ore more simple type constructors
    of each possible kind, and test_repn.m uses them to define types
    that use each possible kind of complex type representation.

tests/valid_make_int/Mmakefile:
tests/valid_make_int/Mercury.options:
    Enable the new test case.
2020-05-28 07:41:44 +10:00
Zoltan Somogyi
9ead91a087 Add a test for Mantis bug #506.
tests/valid_make_int/bug506.m:
tests/valid_make_int/bug506_sub.m:
    The test case. bug506_sub.m defines a type whose name is a Mercury
    operator; we test whether the compiler can read its .int3 file
    when generating the .int file of bug506.m.

tests/valid_make_int/Mmakefile:
    Enable the new case, after adding infrastructure for handling
    multi-module programs.
2020-05-18 00:00:13 +10:00
Zoltan Somogyi
031c7194cd Bring moose's programming style up to date. 2020-05-17 22:59:13 +10:00
Zoltan Somogyi
afe2887882 Remove stale references to test subdirs.
A long time ago, test directories such as hard_coded had subdirectories
such as hard_coded/typeclasses. These have since been flattened out
(e.g. hard_coded/typeclasses is now just typeclasses), but there were
still remnants of the old approach. This diff deletes those remnants.

tests/*/Mmakefile:
    Delete the TESTS_DIR and the SUBDIRS mmake variables; TESTS_DIR
    was always set to "..", and SUBDIRS to the empty string.

    Delete any references to the make variable NOT_WORKING, since
    it is never used.

tests/Mmake.common:
    Document that Mmakefiles in test directories don't have to set
    TESTS_DIR and SUBDIRS anymore. Fix the formatting of the documentation
    of the make variables they do still have to set.

    Delete the targets and actions for handling subdirectories of
    test directories, since there aren't any.

tests/Mmakefile:
    Simplify some code.
2020-04-14 11:23:12 +10:00
Zoltan Somogyi
aea3b98033 Test the process of making .int files.
tests/Mmakefile:
tools/bootcheck:
    Add invalid_make_int and valid_make_int as new test directories.

tests/invalid_make_int/missing_interface_import.m:
tests/invalid_make_int/missing_interface_import.int_err_exp:
tests/invalid_make_int/missing_interface_import.int_err_exp2:
    Move this test case from invalid to invalid_make_int, since it was
    *already* testing the error message we get from "mmc --make-interface".

tests/invalid_make_int/Mercury.options:
tests/invalid_make_int/Mmakefile:
    Set up testing of whether we get the right error messages during
    the process of making .int files.

tests/Mmake.common:
    Provide a way for tests in invalid_make_int to compare a .int_err file
    against several .int_err_exp* files.

tests/invalid/Mercury.options:
tests/invalid/Mmakefile:
    Delete references to the test case moved to invalid_make_int.

tests/valid_make_int/bug499.m:
    Add the test case that motivated this change.

tests/valid_make_int/Mercury.options:
tests/valid_make_int/Mmakefile:
    Set up testing of whether we can generate .int files for modules.
2020-04-13 04:14:51 +10:00