Hi, Willy > [...] > before: > > // ppc64le > $ size nolibc-test > text data bss dec hex filename > 27916 8 80 28004 6d64 nolibc-test > > // mips > $ size nolibc-test > text data bss dec hex filename > 23276 64 64 23404 5b6c nolibc-test > > after: > > // ppc64le > $ size nolibc-test > text data bss dec hex filename > 27736 8 80 27824 6cb0 nolibc-test > > // mips > $ size nolibc-test > text data bss dec hex filename > 23036 64 64 23164 5a7c nolibc-test > > Suggested-by: Willy Tarreau <w@xxxxxx> > Link: https://lore.kernel.org/lkml/20230806095846.GB10627@xxxxxx/ > Link: https://lore.kernel.org/lkml/20230806134348.GA19145@xxxxxx/ > Signed-off-by: Zhangjin Wu <falcon@xxxxxxxxxxx> > --- > > v2 here is further fix up argument with 'const' in the type and also > support "void *" argument, v1 is [1]. > > Tested on many architectures (i386, x86_64, mips, ppc64) and gcc version > (from gcc 4.8-13.1.0), compiles well without any warning and errors and > also with smaller size. > > [1]: https://lore.kernel.org/lkml/20230806131921.52453-1-falcon@xxxxxxxxxxx/ > > --- > tools/include/nolibc/sys.h | 52 ++++++++++++++++++++++++++++++-------- > 1 file changed, 41 insertions(+), 11 deletions(-) > > diff --git a/tools/include/nolibc/sys.h b/tools/include/nolibc/sys.h > index 56f63eb48a1b..9c7448ae19e2 100644 > --- a/tools/include/nolibc/sys.h > +++ b/tools/include/nolibc/sys.h > @@ -35,15 +35,45 @@ > * (src/internal/syscall_ret.c) and glibc (sysdeps/unix/sysv/linux/sysdep.h) > */ > > -static __inline__ __attribute__((unused, always_inline)) > -long __sysret(unsigned long ret) > -{ > - if (ret >= (unsigned long)-MAX_ERRNO) { > - SET_ERRNO(-(long)ret); > - return -1; > - } > - return ret; > -} > +/* > + * Whether 'type' is a signed type or an unsigned type. Supports scalar types, > + * bool and also pointer types. (from include/linux/compiler.h) > + */ > +#define __is_signed_type(type) (((type)(-1)) < (type)1) > + > +/* __auto_type is used instead of __typeof__ to workaround the build error > + * 'error: assignment of read-only variable' when the argument has 'const' in > + * the type, but __auto_type is a new feature from newer version and it only > + * work with 'const' from gcc 11.0 (__GXX_ABI_VERSION = 1016) > + * https://gcc.gnu.org/legacy-ml/gcc-patches/2013-11/msg01378.html > + */ > + > +#if __GXX_ABI_VERSION < 1016 > +#define __typeofdecl(arg) long > +#define __typeofconv1(arg) (long) > +#define __typeofconv2(arg) (long) > +#else > +#define __typeofdecl(arg) __auto_type > +#define __typeofconv1(arg) > +#define __typeofconv2(arg) (__typeof__(arg)) > +#endif > With nolibc-test, we did more tests. for ppc64le (long better): // __auto_type $ size nolibc-test text data bss dec hex filename 27736 8 80 27824 6cb0 nolibc-test // long $ size nolibc-test text data bss dec hex filename 27612 8 80 27700 6c34 nolibc-test for ppc64 (long better): // __auto_type $ size nolibc-test text data bss dec hex filename 27136 1880 80 29096 71a8 nolibc-test // long $ size nolibc-test text data bss dec hex filename 27012 1880 80 28972 712c nolibc-test A further test on x86_64 (__auto_type better): // __auto_type $ size nolibc-test text data bss dec hex filename 22206 8 88 22302 571e nolibc-test // long $ size nolibc-test text data bss dec hex filename 22347 8 88 22443 57ab nolibc-test And i386 (almost the same): // __auto_type $ size nolibc-test text data bss dec hex filename 19718 4 52 19774 4d3e nolibc-test // long $ size nolibc-test text data bss dec hex filename 19717 4 52 19773 4d3d nolibc-test arm64 (__auto_type better): // __auto_type $ size nolibc-test text data bss dec hex filename 25764 8 80 25852 64fc nolibc-test // long $ size nolibc-test text data bss dec hex filename 26004 8 80 26092 65ec nolibc-test arm (the same): // __auto_type $ size nolibc-test text data bss dec hex filename 19595 0 52 19647 4cbf nolibc-test // long $ size nolibc-test text data bss dec hex filename 19595 0 52 19647 4cbf nolibc-test riscv64 (__auto_type better): // __auto_type $ size nolibc-test text data bss dec hex filename 21814 8 80 21902 558e nolibc-test // long $ size nolibc-test text data bss dec hex filename 21912 8 80 22000 55f0 nolibc-test s390 (__auto_type better): // __auto_type $ size nolibc-test text data bss dec hex filename 22302 0 80 22382 576e nolibc-test // long $ size nolibc-test text data bss dec hex filename 22438 0 80 22518 57f6 nolibc-test As a summary, in nolibc-test, for 32-bit architectures, __auto_type has the same as long, for 64-bit architecture, __auto_type has less size than long, only ppc64/ppc64le has reverse result. BR, Zhangjin > +#define __sysret(arg) \ > +({ \ > + __typeofdecl(arg) __sysret_arg = __typeofconv1(arg)(arg); \ > + if (__is_signed_type(__typeof__(arg))) { \ > + if (__sysret_arg < 0) { \ > + SET_ERRNO(-(long)__sysret_arg); \ > + __sysret_arg = __typeofconv2(arg)(-1L); \ > + } \ > + } else { \ > + if ((unsigned long)__sysret_arg >= (unsigned long)-MAX_ERRNO) { \ > + SET_ERRNO(-(long)__sysret_arg); \ > + __sysret_arg = __typeofconv2(arg)(-1L); \ > + } \ > + } \ > + (__typeof__(arg))__sysret_arg; \ > +}) > > /* Functions in this file only describe syscalls. They're declared static so > * that the compiler usually decides to inline them while still being allowed > @@ -94,7 +124,7 @@ void *sbrk(intptr_t inc) > if (ret && sys_brk(ret + inc) == ret + inc) > return ret + inc; > > - return (void *)__sysret(-ENOMEM); > + return __sysret((void *)-ENOMEM); > } > > > @@ -682,7 +712,7 @@ void *sys_mmap(void *addr, size_t length, int prot, int flags, int fd, > static __attribute__((unused)) > void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset) > { > - return (void *)__sysret((unsigned long)sys_mmap(addr, length, prot, flags, fd, offset)); > + return __sysret(sys_mmap(addr, length, prot, flags, fd, offset)); > } > > static __attribute__((unused)) > -- > 2.25.1 > >