Messages in this thread Patch in this message | | | Date | Mon, 18 Mar 2019 14:31:13 -0700 | From | Matthias Kaehlcke <> | Subject | Re: [PATCH] lib: Add shared copy of __lshrti3 from libgcc |
| |
On Fri, Mar 15, 2019 at 01:54:50PM -0700, Matthias Kaehlcke wrote: > The compiler may emit calls to __lshrti3 from the compiler runtime > library, which results in undefined references: > > arch/x86/kvm/x86.o: In function `mul_u64_u64_shr': > include/linux/math64.h:186: undefined reference to `__lshrti3' > > Add a copy of the __lshrti3 libgcc routine (from gcc v4.9.2). > > Include the function for x86 builds with clang, which is the > environment where the above error was observed. > > Signed-off-by: Matthias Kaehlcke <mka@chromium.org>
With "Revert "kbuild: use -Oz instead of -Os when using clang" (https://lore.kernel.org/patchwork/patch/1051932/) the above error is fixed, a few comments inline for if the patch is resurrected in the future because __lshrti3 is emitted in a different context.
> diff --git a/include/linux/libgcc.h b/include/linux/libgcc.h > index 32e1e0f4b2d0..a71036471838 100644 > --- a/include/linux/libgcc.h > +++ b/include/linux/libgcc.h > @@ -22,15 +22,26 @@ > #include <asm/byteorder.h> > > typedef int word_type __attribute__ ((mode (__word__))); > +typedef int TItype __attribute__ ((mode (TI)));
Consider using __int128 instead. Definition and use need a 'defined(__SIZEOF_INT128__)' guard (similar for mode (TI)), since these 128 bit types aren't supported on all platforms.
> #ifdef __BIG_ENDIAN > struct DWstruct { > int high, low; > }; > + > +struct DWstruct128 { > + long long high, low; > +};
This struct isn't needed, struct DWstruct can be used.
> diff --git a/lib/lshrti3.c b/lib/lshrti3.c > new file mode 100644 > index 000000000000..2d2123bb3030 > --- /dev/null > +++ b/lib/lshrti3.c > @@ -0,0 +1,31 @@ > +// SPDX-License-Identifier: GPL-2.0 > + > +#include <linux/export.h> > +#include <linux/libgcc.h> > + > +long long __lshrti3(long long u, word_type b) use TItype for input/output, which is what gcc does, though the above matches the interface in the documentation.
> +{ > + DWunion128 uu, w; > + word_type bm; > + > + if (b == 0) > + return u; > + > + uu.ll = u; > + bm = 64 - b; > + > + if (bm <= 0) { > + w.s.high = 0; > + w.s.low = (unsigned long long) uu.s.high >> -bm;
include <linux/types.h> and use u64 instead of unsigned long long.
| |