I don't know why the problem only surfaced recently, but it seems that its
underlying cause is a misunderstanding about the import_status of predicates.
In integer.m in the library, the predicate integer.to_string calls the function
(a) String.++ is marked (correctly) as opt_imported.
(b) The test predicate pred_info_is_imported FAILS for opt_imported predicates.
(c) This causes make_rtti_proc_label to put "no" into the pred_is_imported
field of the rtti_proc_label for string.++.
(d) This rtti_proc_label is put into the element of the call_site_static_data
list for integer.to_string that corresponds to the call to string.++
as the rtti_proc_label of the callee.
(e) When the time comes to write out the call_site_static structures,
layout_out.m invokes make_proc_label_from_rtti to convert this
rtti_proc_label in the call_site_static_data to a plain, non-RTTI
proc_label. However, since the current module name ("integer") does not
match the name of the module that defines the function ("string") AND
the function is not marked as imported, make_user_proc_label (invoked
from make_proc_label_from_rtti) believes that this means that this module
generates code for the callee (as we do for some opt_imported procedures).
(f) For procedures for which we generate target code in a different module
than their defining module, we generate different labels for them
than the label for the code for the procedure in its own module.
We derive the name of a procedure's proc_static structure directly from
its label, so this difference holds for the names of proc_static structures
as well as for labels.
(g) This lead to the problem, which was that the call_site_static for this call
site referred to the proc_static for string.++ defined in integer.c
(as opposed to string.++ defined in string.c), since integer.c did not
actually generate code for string.++, there was no such proc_static.
This should be a link error, but it isn't, due to the requirement on unix
linkers of being compatible with Fortran's ancient semantics (specifically,
Fortran's common areas). Instead, the C compiler happily allocates memory
for the undefined symbol and fills it with zeros as if it were a
(h) The assertion violation in mercury_deep_profiling.c occurs because the
call_site_static refers to this bogus proc_static, but of course no module
writes out this proc_static.