[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Tinycc-devel] Add support of musl-libc to tinycc

From: avih
Subject: Re: [Tinycc-devel] Add support of musl-libc to tinycc
Date: Fri, 12 May 2017 08:40:11 +0000 (UTC)

Re: 4. NAN in a (static) initializer and "Error: division by zero in constant".

It seems the issue stems from musl's math.h defining NAN as (0.0f/0.0f) if it's
not GNUC > 3.3, and tcc rejecting it.

A program to reproduce the issue (after math.h expands NAN):
double x = (0.0f/0.0f); int main() { return 0; }

(note: gcc doesn't complain about this exact program - without using NAN).

The C99 spec, if I read the correct one, says "The macro NAN is defined if and
only if the implementation supports quiet NaNs for the float type. It expands
to a constant _expression_ of type float representing a quiet NaN".

However, "Shiz" pointed me to the C99 spec, suggesting that 0.0/0.0 should also
be allowed in a static initializer (F.7.4 Constant expressions). I'm not sure I
interpret it the same though.

I think the issue is one of the following:

1. 0.0/0.0 should not be allowed in a static initializer, and musl's math.h
needs to somehow know what to do with NAN if it's not GNUC (where it uses
__builtin_nanf("") ).

2. 0.0/0.0 should be allowed in a static initializer, and it should be fixed in
tcc. I'm not sure if this contradicts a comment in tccgen.c:1836 "NOTE: we only
do constant propagation if finite number (not NaN or infinity) (ANSI spec)".
It's also possible that C99 changed it after that comment was written.

Trying to comment out this float error at tccgen.c:1847 ends up with a
different error though: "error: initializer element is not constant".

Not sure what the solution should be here, and especially if it's (1), then how
should math.h handle (or not) NAN.

On Thursday, May 11, 2017 10:53 PM, avih <address@hidden> wrote:

I tested tcc on alpine linux (has gcc and musl-libc only) and noticed:

1. tcc commit 1094891 broke musl detection on alpine.
Maybe because alpine has /lib64/ld-linux-x86-64.so.2 (which is a symlink to
/lib/libc.musl-x86_64.so.1 )

The following are with commit 1094891 reverted.

2. While all the tests now pass, if tcc is used to build tcc again, tests fail.
See procedure[2] and log below.

3. It seems that (with musl) tcc needs stdarg.h included before stdio.h, or else
it segfaults at runtime. musl's maintainer says that musl doesn't support
compiler std dirs, and that it expects the compiler to have the intrinsics
__builtin_va*. See discussion[3] log below.

I then used tcc on this system to build mpv ( https://mpv.io , ~200 C files) and
had some issues. I don't think all of them are tcc's fault, but with gcc on the
same system it builds cleanly.

4. Initializers of NAN fail with "division by 0 in a constant", but I was _not_
able to reproduce it with a minimal test case. My non-minimal case is compiling
mpv . Here's one such place which fails:
const struct filter_window mp_filter_windows[] = {
    {"kaiser",         1,   kaiser,   .params = {6.33, NAN} },

where the struct has double params[2];

5. tcc dislikes some #defines (I couldn't reproduce in a minimal case), e.g.:
A: #define HAVE_CHMAP_API \
    (defined(SND_CHMAP_API_VERSION) && SND_CHMAP_API_VERSION >= (1 << 16))
B: #define KEEP_DEVICE (defined(SNDCTL_DSP_RESET) && !defined(__NetBSD__))

In A I had to remove the outer parenthesis, and in B I had to rewrite it differently.

6. Some redifinition warnings on _IO* .This _seems_ unrelated to tcc, but still
doesn't happen with gcc. It's weird since tcc doesn't define those (except on
windows, but I'm testing on linux). See log[6] below.

All that being said, after replacing the NANs with 0, moving include stdarg to
the top, and modifying the #define, mpv builds with tcc cleanly and runs fine
on alpine (with video, opengl, audio, etc).

[2] procedure to build tcc with tcc:
Start within the tcc dir, and then mkdir build && cd build.

../configure --prefix=$(pwd)/dist && make && make test && make install
That succeeded. Now rebuild with tcc:

../configure --cc=$(pwd)/dist/bin/tcc && make && make test
This fails at some tests. See attached tcc-rebuild-log.txt.

[3] discussion about tcc's stdarg.h:

<avih> dalias: so tcc now works with musl. i still have an issue though if stdio.h (possibly others too) come before stdarg.h in the program.  tcc has its own prioritized include dirs with stdarg.h. i'm trying to figure out musl's expectations with regards to this. i'm looking at bits/alltypes.h, does musl expects the compiler to have an intrinistic define of __DEFINED_va_list or __DEFINED___isoc_va_list ?
<avih> (if stdarg.h is included first then va_list et al work fine with tcc+musl)
<dalias> musl does not support compiler-provided std headers
<Shiz> dalias: even stdarg?
<dalias> the libc headers must come first in include path
<Shiz> or stdint?
<dalias> yes
<avih> what's the relation between the compiler's va_list and musl?
<Shiz> i thought some stuff came from the compiler
<dalias> no, that's a glibcism
<dalias> bsd doesn't work that way and musl doesn't either
<avih> dalias: so how should the compiler expose it such that it can be used correctly?
<Shiz> it should provide the right primitives
<dalias> by providing the intrinsics (__builtin_va*)
<Shiz> musl relies on __builtin_va_list and the likes
<avih> gotcha.
<dalias> or you could use a silently pre-included header to define them as macros
<dalias> but that's a hack
<dalias> the compiler itself could just predefine them as macros if it doesn't want real intrinsics
<avih> dalias: you mean instead of using stdarg.h in a prioritized dir?
<dalias> yes
<avih> k, thx

[6] the same warning happens for _IOC, _IO, _IOR, _IOW and _IOWR :
In file included from audio/out/ao_oss.c:46:
In file included from /usr/include/sys/soundcard.h:1:
In file included from /usr/include/linux/soundcard.h:40:
In file included from /usr/include/linux/ioctl.h:4:
In file included from /usr/include/asm/ioctl.h:1:
/usr/include/asm-generic/ioctl.h:77: warning: _IOWR redefined

On Monday, May 8, 2017 7:29 PM, Marc Vertes <address@hidden> wrote:

> Le 7 mai 2017 à 08:16, Michael Matz <address@hidden> a écrit :
> On debain, if you have libc6-dev and musl-dev installed you get a strange mix of glibc and musl objects and shared libraries linked into the exe. E.g. in the above it picks up /usr/lib/x86_64-linux-gnu/libc.a (from glibc), which has TPOFF32 relocs and those aren't handled by TCC.
> Removing libc6-dev, installing musl-tools, and using musl-gcc for compilation ensures that there's no mixture at least.  But that then fails because TCC itself isn't prepared to look into e.g. /usr/include/x86_64-linux-musl for standard headers like e.g. stdio.h, neither does it look into /usr/lib/x86_64-linux-musl/ for startup files like crt1.o.  So, yeah, the detection/support of musl is early and doesn't work with the split-mind approach that debian is using.
> It does work for the setup of musl as the main libc, like with alpine linux; so I'm not sure the detection should be disabled or rather be improved (or there should perhaps be a configure option to override the detection by users).

To address that, I committed a first patch on mob to improve musl or uclibc detection:

Now, configure does not enable musl or uclibc native support if a GNU
linker is already present. This avoids interference for example on a
Debian platform with musl-dev installed. More work is required
to select musl libc in that case, with additional configure flags,
i.e. --enable-musl and further code in tcc.h etc.


Tinycc-devel mailing list

reply via email to

[Prev in Thread] Current Thread [Next in Thread]