[m-users.] Mercury macro trouble
Julien Fischer
jfischer at opturion.com
Sun May 26 15:01:06 AEST 2024
Hi,
On Fri, 24 May 2024 at 22:31, Volker Wysk <post at volker-wysk.de> wrote:
> Some quotes from this list:
>
> M. McDonough on 2023-07-19:
> "After some debugging, I now suspect that I know the answer, and it's that
> MR_list_cons isn't safe to call directly outside of a foreign_proc because
> it can interact with the Mercury register usage."
>
> Peter Wang on 2023-07-20:
> "The problem is that the argument of MR_list_cons(), the call to
> CreateNode(), is not evaluated before MR_list_cons() starts doing
> anything. You should make the call CreateNode() first, assign the
> result to a variable, then perform the MR_list_cons()."
>
> M. McDonough on 2024-04-27:
> "I just want to note this, as it's caused me issues in the past. It's a
> bad idea to have anything other than a variable or integral expression
> (no function calls, no macros, etc) as the argument to MR_list_cons
> (and I would generally say any of the MR_* macros unless you've read
> them carefully). You can end up with issues where things are executed
> in an unexpected order, and in particular on the low-level C grades,
> this can cause big issues with Mercury registers being clobbered
> leading to very hard to debug issues with seemingly impossible
> behavior."
>
> I think, this is bad and should be addressed.
>
> The obvious solution would be to use inline C functions with the same names
> as the macros, instead. Gcc's statement expressions aren't needed.
>
> So I'm asking the Mercury team to scrap all those macros and use inline
> functions instead. :-)
The intended use of those macros was for the implementation of the Mercury
system itself. They aren't inline C function because in that role
it's probably not
useful for them to be inline C functions. (To say nothing of the fact
that when those
macros were originally written, C did not have a standard notion of an inline
function.)
The secondary role of these macros as a mechanism by which users can
manipulate lists in foreign code has arisen, more or less, by accident.
> No, seriously, I can understand that the Mercury team is reluctant to touch
> those long-proven macros.
Whether those macros are appropriate for users is another question.
As C macros, they (obviously) have all the inherent issues with C macro
argument evaluation (as in the above examples), but that's not really a Mercury
problem.
> This leads to the second best solution: Wrap those macros in inline
> functions. And instruct the user to use them instead of the macros. For
> instance, like this:
>
> static inline MR_Word mr_list_cons(MR_Word head, MR_Word tail)
> {
> MR_Word result = MR_list_cons(head, tail);
> return result;
> }
>
> This should amend the problem. Or am I missing something? It seems odd to me
> that this obvious solution hasn't been implemented already.
My suggestion would be that the list module in the standard library
provide function
versions of these operations (as indeed it does for the C# and Java backends).
Users should be directed to those, instead of the runtime macros ...
... or users should just foreign export pragmas the operations they
need to manipulate
lists in foreign code. As indeed you would need to do if you wanted
to manipulate just
about any other data structure in the Mercury standard library from
foreign code. This
approach also automatically handles whether arguments need to be boxed etc.
Julien.
More information about the users
mailing list