Skip to content

dmd tests do not work with FreeBSD 14 due to dmd not supporting gnu asm #20825

@jmdavis

Description

@jmdavis

On FreeBSD 14, dmd-test fails with

FAILED targets:
- runnable/helloc.c
- compilable/stdcheaders.c
gmake: *** [Makefile:86: dmd-test] Error 1

Both of those files #include stdlib.h, so while the actual error isn't given, I'm pretty sure that the issue here is that dmd can't handle gnu assembly, and stdlib.h uses gnu assembly on FreeBSD 14 (but not 13, which is why the FreeBSD 13 tests do not fail with this problem in the CI), since if you write a test that tries to use importC on stdlib.h on FreeBSD 14, it will fail for that reason. Specifically, it's this section of stdlib.h that's the problem:

/*
 * In FreeBSD 14, the prototype of qsort_r() was modified to comply with
 * POSIX.  The standardized qsort_r()'s order of last two parameters was
 * changed, and the comparator function is now taking thunk as its last
 * parameter, and both are different from the ones expected by the historical
 * FreeBSD qsort_r() interface.
 *
 * Apply a workaround where we explicitly link against the historical
 * interface, qsort_r@FBSD_1.0, in case when qsort_r() is called with
 * the last parameter with a function pointer that exactly matches the
 * historical FreeBSD qsort_r() comparator signature, so applications
 * written for the historical interface can continue to work without
 * modification.
 */
#if defined(__generic) || defined(__cplusplus)
void __qsort_r_compat(void *, size_t, size_t, void *,
	    int (*)(void *, const void *, const void *));
__sym_compat(qsort_r, __qsort_r_compat, FBSD_1.0);
#endif
#if defined(__generic) && !defined(__cplusplus)
#define	qsort_r(base, nel, width, arg4, arg5)				\
    __generic(arg5, int (*)(void *, const void *, const void *),	\
        __qsort_r_compat, qsort_r)(base, nel, width, arg4, arg5)
#elif defined(__cplusplus)
__END_DECLS
extern "C++" {
static inline void qsort_r(void *base, size_t nmemb, size_t size,
    void *thunk, int (*compar)(void *, const void *, const void *)) {
	__qsort_r_compat(base, nmemb, size, thunk, compar);
}
}

I'm not sure which version of the __sym_compat macro from sys/cdefs.h is compiled in, either

#define	__sym_compat(sym,impl,verid)	\
	__asm__(".symver " #impl ", " #sym "@" #verid)

or

#define	__sym_compat(sym,impl,verid)	\
	__asm__(".symver impl, sym@verid")

but either way, a gnu assembly instruction is being used, and dmd errors out when it encounters it.

So, in order for FreeBSD 14 to pass the dmd test suite, either dmd needs to actually learn to handle gnu assembly at least far enough to compile stdlib.h rather than choking on the assembly instruction, or the tests are going to need to be changed to not use importC on stdlib.h on FreeBSD.

#20607 is essentially the same issue except for the druntime tests, though obviously, the fix is different if the tests are going to be changed rather than improving dmd's capabilities to actually be able to handle stdlib.h on FreeBSD 14.

Personally, I'd really like it if dmd could actually compile code that uses gnu assembly code even if it's simply by skipping any symbols that have gnu assembly on them. This is not the first time that FreeBSD has used gnu assembly in such a fashion in system headers, and it likely won't be the last. And given how common gnu assembly is, it can't be all that uncommon for C headers to use it somewhere, which is going to cause problems with importC as things stand. Of course, the ideal situation would be if dmd could actually compile the assembly code properly like ldc or gdc would be able to do, but presumably, that's a large undertaking.

Either way, the handling of stdlib.h and importC needs to be sorted out somehow, or we won't be able to update the CI to test FreeBSD 14. The expected EoL for FreeBSD 13 is in April of next year.

Metadata

Metadata

Assignees

No one assigned

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions