[m-dev.] Bug 321

Paul Bone paul at bone.id.au
Fri Feb 21 18:16:52 AEDT 2014


I'm tracking down bug 321.  https://www.mercurylang.org/bugs/view.php?id=321

As you recall this is the symptom:

    The C linker gives me errors such as:

    paul at oxygen> mmc --rebuild test -O2 --intermodule-optimization
    Making Mercury/int3s/test.int3
    Making Mercury/ints/test.int
    Making Mercury/opts/test.opt
    Making Mercury/cs/test.c
    Making Mercury/os/test.o
    Making test
    ** Error making `test'.
    Mercury/os/test.o: In function `<predicate 'test.try_divide'/3 mode
    test.c:(.text+0xe6): undefined reference to `<predicate
    'exception.wrap_success_or_failure'/2 mode 0>'
    collect2: error: ld returned 1 exit status

After looking at the exception.m code and the HLDS dumps during compilation
of my test.m I found that:

    The linker can't find an address for: wrap_success_or_failure/2
    But it can find addresses for: get_determinism/2

Both predicates are called by the same code in the HLDS representation of
test.m but one works and what doesn't.

So I looked at readelf(1) dump of libmer_std.so's symbol table.
get_determinism/2 is exported globally and wrap_success_or_failure/2 is
exported locally.
Both are declared and defined in the implementation section of the exception
module.  So now I want to know why is one being treated differently.

The relevant code seems to be on line 2186 of compiler/intermod.m, where the
compiler performs a fixpoint analysis so that it knows what else needs to be
opt-exported.  Searching further (line 289) I find should_be_processed/8
which appears to determine if a predicate should be opt-exported or not,
I'm not sure as comments are scarce.

Is there anyone familiar with this part of the compiler?  My clues are the
above, plus wrap_success_or_failure takes a higher order argument and is
part of a lambda expression itself, during compilation (in the HLDS) it
appears to be partially applied.

One specific question I have is how does the compiler decide between:
    + opt-exporting a predicate
    + making a predicate available to another module because a caller is
      opt-exported and this predicate is otherwise local.
    + leaving the predicate local.

I haven't found the code for the second case.


Paul Bone

More information about the developers mailing list