On x86_64, long double
is an 80-bit extended precision float with a size and alignment of 16 (only the first 10 are used), passed in x87 registers. On aarch64, it is a IEEE 754 binary128 emulated in software and passed in 128-bit vector registers.
Although long double
doesn't seem to be used too heavily, it is problematic since some inline functions in musl's math.h
use it.
If we didn't generate code for static inline
functions unless they are called or have their address taken, we could just ignore this for now. This would require generating code separately from parsing statements, rather than together as we are doing now.
To actually implement this, we will need some support from QBE to pass long double
arguments in the right registers. Perhaps this could be done by introducing two new register types, x
and q
. There would need to be some softfp code for aarch64. https://bellard.org/softfp/ looks like a good option, but would require implementing __int128
.
After an update my nixos headers are also trying to use __float128.
Which headers, specifically? Is this due to defining
__GNUC__=4
instead of just undefining it?This is a bit tricky since we need to define
__GNUC__
to get the libc to use certain necessary built-ins (like__builtin_alloca
), but we don't support other extensions like__float128
.
Yeah, GNUC=4 is the reason:
# 32 "/nix/store/f3l058q0zvnzr7nvl0jj789pyvljqadw-glibc-2.27-dev/include/stdlib.h" 2 3 4 # 1 "/nix/store/f3l058q0zvnzr7nvl0jj789pyvljqadw-glibc-2.27-dev/include/bits/waitflags.h" 1 3 4 # 40 "/nix/store/f3l058q0zvnzr7nvl0jj789pyvljqadw-glibc-2.27-dev/include/stdlib.h" 2 3 4 # 1 "/nix/store/f3l058q0zvnzr7nvl0jj789pyvljqadw-glibc-2.27-dev/include/bits/waitstatus.h" 1 3 4 # 41 "/nix/store/f3l058q0zvnzr7nvl0jj789pyvljqadw-glibc-2.27-dev/include/stdlib.h" 2 3 4 # 55 "/nix/store/f3l058q0zvnzr7nvl0jj789pyvljqadw-glibc-2.27-dev/include/stdlib.h" 3 4 # 1 "/nix/store/f3l058q0zvnzr7nvl0jj789pyvljqadw-glibc-2.27-dev/include/bits/floatn.h" 1 3 4 # 74 "/nix/store/f3l058q0zvnzr7nvl0jj789pyvljqadw-glibc-2.27-dev/include/bits/floatn.h" 3 4 typedef _Complex float __cfloat128 ; # 86 "/nix/store/f3l058q0zvnzr7nvl0jj789pyvljqadw-glibc-2.27-dev/include/bits/floatn.h" 3 4 typedef __float128 _Float128;
I just worked around it with these:
+ + /* XXX Workaround */ + "-D", "__float128=double"
case T_COMPLEX: - fatal("_Complex is not yet supported"); + // fatal("_Complex is not yet supported"); + next(); break;
Ugh, forgive the screwed up formatting, you get the idea.
Okay, I think we should be defining both
__GNUC__
and__GNUC_MINOR__
. I think the minor version of thecpp
used is leaking through. If it is at least 3 (and__GNUC__ >= 4
), glibc's headers define__HAVE_FLOAT128=1
. I'm using 8.2.0, so I didn't run into the issue.Looking at musl's headers, I think
__GNUC__=3
and__GNUC_MINOR__=3
might be the sweet spot. Can you check if you run into any problems with that?
Yup, that works for me for stage3 build.
Noting that this is a blocker for compiling tinycc with cproc