long double

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.

Assigned to
2 years ago
2 years ago

~ach 2 years ago

After an update my nixos headers are also trying to use __float128.

~mcf 2 years ago

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.

~ach 2 years ago

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();

~ach 2 years ago

Ugh, forgive the screwed up formatting, you get the idea.

~mcf 2 years ago

Okay, I think we should be defining both __GNUC__ and __GNUC_MINOR__. I think the minor version of the cpp 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?

~ach 2 years ago

Yup, that works for me for stage3 build.

Register here or Log in to comment, or comment via email.