mirror of
https://github.com/Mercury-Language/mercury.git
synced 2026-04-17 18:33:58 +00:00
This fixes Mantis bug #493. compiler/common.m: Don't apply the common_struct optimization if doing so could possibly invalidate the annotations generated by mark_static_terms.m, which the MLDS code generator relies on. Move the tests for the applicability of the common_struct optimization for both construction and deconstruction unifications next to each other. Add XXXs about possible problems this code may have when applied to code that does region based memory allocation. tests/valid/bug493.m: A simplified version of the Mantis test case. tests/valid/Mmakefile: tests/valid/Mercury.options: Enable the new test case, and specify the options that originally caused the bug to manifest itself.
72 lines
2.7 KiB
Mathematica
72 lines
2.7 KiB
Mathematica
%---------------------------------------------------------------------------%
|
|
% vim: ts=2 sw=2 ft=mercury
|
|
%---------------------------------------------------------------------------%
|
|
%
|
|
% This is a regression test for Mantis bug #493.
|
|
%
|
|
% The bug was a compiler abort in the MLDS code generator when processing
|
|
% the binding of Range in the parse predicate. The sequence of events
|
|
% leading to this abort was as follows.
|
|
%
|
|
% 1 The compiler inlines dash in parse_range.
|
|
% 2 The compiler inlines parse_range (with dash inlined) in parse.
|
|
% 3 The mark_static_terms pass marks both of the construction unifications
|
|
% involved in Range = range(unicode(0x2d)) as being done statically.
|
|
% 4 The mark_static_terms pass marks the construction unification
|
|
% Res = [Range] as also being done statically.
|
|
% 5 The pre-code-generation invocation of simplification runs the common
|
|
% structure optimization on the body of parse, and replaces the code
|
|
% that constructs Range with code that assigns the unnamed internal
|
|
% variable representing the first element of Us0 to Range, exploiting
|
|
% the coincidence that both are bound to unicode(0x2d).
|
|
% 6 When the MLDS code generator processes that assignment to Range,
|
|
% it does not mark Range is being statically constructed, because
|
|
% it isn't.
|
|
% 7 When the MLDS code generator processes the construction unification
|
|
% that implements Res = [Range], it does so using the code path that
|
|
% constructs Res statically, since mark_static_terms said that Res
|
|
% should be constructed statically. However, this requires all the variables
|
|
% on the right hand side of the construction unification to be in the
|
|
% database of statically constructed terms, which (due to steps 5 and 6
|
|
% above) it is not. This violation of this code path's precondition
|
|
% causes the abort.
|
|
%
|
|
% The actual culprit is step 5. By replacing a "construct statically"
|
|
% construction unification of Range with an assignment, it broke all later
|
|
% "construct statically" construction unifications in which Range occurred
|
|
% on the right hand side.
|
|
%
|
|
%---------------------------------------------------------------------------%
|
|
|
|
:- module bug493.
|
|
:- interface.
|
|
|
|
:- import_module list.
|
|
|
|
:- type range
|
|
---> range(unicode).
|
|
|
|
:- type unicode
|
|
---> unicode(int).
|
|
|
|
:- pred parse(list(unicode)::in, list(unicode)::out, list(range)::out)
|
|
is semidet.
|
|
|
|
:- implementation.
|
|
|
|
parse(Us0, Us, Res) :-
|
|
parse_range(Us0, Us, Range),
|
|
Res = [Range].
|
|
|
|
:- pred parse_range(list(unicode)::in, list(unicode)::out, range::out)
|
|
is semidet.
|
|
|
|
parse_range(Us0, Us, Range) :-
|
|
Us0 = [unicode(0x2d) | Us],
|
|
Range = dash.
|
|
|
|
:- func dash = range.
|
|
:- pragma inline(dash/0).
|
|
|
|
dash = range(unicode(0x2d)).
|