Files
mercury/tests/valid/bug544.m
Zoltan Somogyi 9ddb180757 Handle const_var_maps left by add_trail_ops.m.
This fixes Mantis bug #544.

The code of add_trail_ops.m can transform

    <code that adds an entry to const_var_map>

into

    (
        ...
        <code that adds an entry to const_var_map>
        ...
    ;
        ...,
        fail
    )

where the const_var_map in the MLDS code generator records which variables'
values are available as ground terms.

The MLDS code generator used to reset the const_var_map in its main data
structure, the ml_gen_info, at the end of every disjunction (actually,
at the end of every branched control structure) to the value it had
at the start. This was intended to prevent the code following the branched
structure from relying on const_var_map entries that were added to the
const_var_map on *some* branches, but not others. However, in this case,
it has the effect of forgetting the entry added by the first disjunct,
even though

- the code after the disjunction can be reached *only* via the first disjunct,
  and

- the code after the disjunction (legitimately, until add_trail_ops) depended
  on that entry being available.

The fix is to allow the code after a branched control structure to depend
on any const_var_map entry that is present in the final const_var_map
in every branch of the branched control structure whose end is reachable.

The LLDS code generator was not affected by the bug, because it uses
totally separate systems both for implementing trailing, and for keeping
track of what variables' values are available statically. In particular,
it does not rely on operations inserted and the annotations left on
unifications by the add_trail_ops and mark_static_term passes,
having been written long before either module existed.

compiler/hlds_goal.m:
    Document the update above to what may be marked static.

compiler/ml_gen_info.m:
    Document the updated protocol for handling the const_var_map field.

    Use a named type instead of its expansion.

compiler/ml_code_gen.m:
    Make the predicates that generate code for a branch in a branched
    control structure return the final const_var_maps from the branches
    whose endpoints are reachable.

    Add a predicate that computes the consensus of all the gathered
    const_var_maps.

    Compute consensus const_var_maps for if-then-elses and negations.

    Fix some inconsistencies in variable naming.

    Simplify some code.

compiler/ml_disj_gen.m:
    Compute consensus const_var_maps for disjunctions.

compiler/ml_string_switch.m:
compiler/ml_switch_gen.m:
compiler/ml_tag_switch.m:
    Compute consensus const_var_maps for various kinds of switches.

    In some predicates, put related arguments next to each other.

compiler/ml_unify_gen_construct.m:
    Delete "dynamic" from the names of several predicates that also handled
    non-dynamic construction unifications.

    Fix an out-of-date comment.

compiler/mark_static_terms:
    Fix grammar in a comment.

library/map.m:
    Fix a careless bug: when doing a merge in map.common_subset_loop,
    we threw away an entry from the wrong list in one of three cases.

    Make such bugs harder to overlook by

    - deleting the common parts from variable names, leaving the differences
      easier to see, and

    - replacing numeric suffixes for completely separate data structures
      with A and B suffixes.

tests/valid/bug544.m:
    A new test case for the bug.

tests/valid/Mercury.options:
tests/valid/Mmakefile:
    Enable the bug, and run it with -O5.
2022-02-07 17:30:32 +11:00

47 lines
1.4 KiB
Mathematica

%---------------------------------------------------------------------------%
% vim: ts=4 sw=4 et ft=mercury
%---------------------------------------------------------------------------%
:- module bug544.
:- interface.
:- type t1.
:- type t2.
:- pred s(int::in, t2::out) is cc_nondet.
:- implementation.
:- import_module int.
:- import_module list.
:- type t1
---> f(string, int).
:- type t2
---> g(t1, t1)
; i.
s(X, Y) :-
% The bug happened because, after the construction of Result
% was transformed by simplification into a reference to a ground term,
%
% - add_trail_ops.m wrapped a disjunction around this scope,
% in which the first disjunct defines Result, while the second
% disjunct, which could not succeed, did not, but
%
% - ml_disj_gen.m used ml_gen_goal_as_branch_block to generate code
% for each disjunct, and that predicate threw away any changes made
% to the const_var_map during each disjunct.
%
% This meant that when the code generator reached the construction of Y,
% which was marked as being constructed statically by a pass before
% add_trail_ops.m, it could not find Result in the const_var_map.
% The map lookup failure caused a compiler crash.
some [Z] (
(Z = 1 ; Z = 2),
X = Z * Z,
Result = f("hello", 0)
),
Y = g(Result, Result).