diff mbox series

[1/5] Fix {INLINE,INTERNAL}_SYSCALL macros for x32

Message ID 1495563960-669-2-git-send-email-adhemerval.zanella@linaro.org
State Superseded
Headers show
Series Remove sysdep-cancel assembly macro | expand

Commit Message

Adhemerval Zanella Netto May 23, 2017, 6:25 p.m. UTC
From: Adhemerval Zanella <adhemerval.zanella@linaro.com>


The problem for x32 is the {INTERNAL,INLINE}_SYSCALL C macros explicit
cast the arguments to 'long int', thus passing as 32 bits arguments
that should be passed to 64 bits.

Previous x32 implementation uses the auto-generated syscalls from
assembly macros (syscalls.list), so the {INTERNAL,INLINE}_SYSCALL
macros are never used with 64 bit argument in x32 (which are
internally broken for this ILP).

To fix it I used a strategy similar to MIPS64n32 (although both
ABI differs for some syscalls on how top pass 64-bits arguments)
where argument types for kernel call are defined using GCC extension
'typeof' with a arithmetic operation.  This allows 64-bits arguments
to be defined while 32-bits argument will still passed as 32-bits.

I also cleanup the {INLINE,INTERNAL}_SYSCALL definition by defining
'inline_syscallX' instead of constructing the argument passing using
macros (it adds some readability) and removed the ununsed
INTERNAL_SYSCALL_NCS_TYPES define (since the patch idea is exactly to
avoid requiric explicit types passing).

Tested on x86_64 and x32.

	* sysdeps/unix/sysv/linux/x86_64/sysdep.h
	(INTERNAL_SYSCALL_NCS_TYPES): Remove define.
	(LOAD_ARGS_0): Likewise.
	(LOAD_ARGS_1): Likewise.
	(LOAD_ARGS_2): Likewise.
	(LOAD_ARGS_3): Likewise.
	(LOAD_ARGS_4): Likewise.
	(LOAD_ARGS_5): Likewise.
	(LOAD_ARGS_6): Likewise.
	(LOAD_REGS_0): Likewise.
	(LOAD_REGS_1): Likewise.
	(LOAD_REGS_2): Likewise.
	(LOAD_REGS_3): Likewise.
	(LOAD_REGS_4): Likewise.
	(LOAD_REGS_5): Likewise.
	(LOAD_REGS_6): Likewise.
	(ASM_ARGS_0): Likewise.
	(ASM_ARGS_1): Likewise.
	(ASM_ARGS_2): Likewise.
	(ASM_ARGS_3): Likewise.
	(ASM_ARGS_4): Likewise.
	(ASM_ARGS_5): Likewise.
	(ASM_ARGS_6): Likewise.
	(LOAD_ARGS_TYPES_1): Likewise.
	(LOAD_ARGS_TYPES_2): Likewise.
	(LOAD_ARGS_TYPES_3): Likewise.
	(LOAD_ARGS_TYPES_4): Likewise.
	(LOAD_ARGS_TYPES_5): Likewise.
	(LOAD_ARGS_TYPES_6): Likewise.
	(LOAD_REGS_TYPES_1): Likewise.
	(LOAD_REGS_TYPES_2): Likewise.
	(LOAD_REGS_TYPES_3): Likewise.
	(LOAD_REGS_TYPES_4): Likewise.
	(LOAD_REGS_TYPES_5): Likewise.
	(LOAD_REGS_TYPES_6): Likewise.
	(TYPEFY): New define.
	(ARGIFY): Likewise.
	(internal_syscall0): Likewise.
	(internal_syscall1): Likewise.
	(internal_syscall2): Likewise.
	(internal_syscall3): Likewise.
	(internal_syscall4): Likewise.
	(internal_syscall5): Likewise.
	(internal_syscall6): Likewise.
	* sysdeps/unix/sysv/linux/x86_64/x32/times.c
	(INTERNAL_SYSCALL_NCS): Remove define.
	(internal_syscall1): Add define.
---
 ChangeLog                                  |  50 ++++++
 sysdeps/unix/sysv/linux/x86_64/sysdep.h    | 251 ++++++++++++++++-------------
 sysdeps/unix/sysv/linux/x86_64/x32/times.c |  24 +--
 3 files changed, 205 insertions(+), 120 deletions(-)

-- 
2.7.4

Comments

Adhemerval Zanella Netto June 29, 2017, 2:15 p.m. UTC | #1
Ping, x86 is the only target AFAIK preventing the sysdep-cancel asm
macro removal.

On 23/05/2017 15:25, Adhemerval Zanella wrote:
> From: Adhemerval Zanella <adhemerval.zanella@linaro.com>

> 

> The problem for x32 is the {INTERNAL,INLINE}_SYSCALL C macros explicit

> cast the arguments to 'long int', thus passing as 32 bits arguments

> that should be passed to 64 bits.

> 

> Previous x32 implementation uses the auto-generated syscalls from

> assembly macros (syscalls.list), so the {INTERNAL,INLINE}_SYSCALL

> macros are never used with 64 bit argument in x32 (which are

> internally broken for this ILP).

> 

> To fix it I used a strategy similar to MIPS64n32 (although both

> ABI differs for some syscalls on how top pass 64-bits arguments)

> where argument types for kernel call are defined using GCC extension

> 'typeof' with a arithmetic operation.  This allows 64-bits arguments

> to be defined while 32-bits argument will still passed as 32-bits.

> 

> I also cleanup the {INLINE,INTERNAL}_SYSCALL definition by defining

> 'inline_syscallX' instead of constructing the argument passing using

> macros (it adds some readability) and removed the ununsed

> INTERNAL_SYSCALL_NCS_TYPES define (since the patch idea is exactly to

> avoid requiric explicit types passing).

> 

> Tested on x86_64 and x32.

> 

> 	* sysdeps/unix/sysv/linux/x86_64/sysdep.h

> 	(INTERNAL_SYSCALL_NCS_TYPES): Remove define.

> 	(LOAD_ARGS_0): Likewise.

> 	(LOAD_ARGS_1): Likewise.

> 	(LOAD_ARGS_2): Likewise.

> 	(LOAD_ARGS_3): Likewise.

> 	(LOAD_ARGS_4): Likewise.

> 	(LOAD_ARGS_5): Likewise.

> 	(LOAD_ARGS_6): Likewise.

> 	(LOAD_REGS_0): Likewise.

> 	(LOAD_REGS_1): Likewise.

> 	(LOAD_REGS_2): Likewise.

> 	(LOAD_REGS_3): Likewise.

> 	(LOAD_REGS_4): Likewise.

> 	(LOAD_REGS_5): Likewise.

> 	(LOAD_REGS_6): Likewise.

> 	(ASM_ARGS_0): Likewise.

> 	(ASM_ARGS_1): Likewise.

> 	(ASM_ARGS_2): Likewise.

> 	(ASM_ARGS_3): Likewise.

> 	(ASM_ARGS_4): Likewise.

> 	(ASM_ARGS_5): Likewise.

> 	(ASM_ARGS_6): Likewise.

> 	(LOAD_ARGS_TYPES_1): Likewise.

> 	(LOAD_ARGS_TYPES_2): Likewise.

> 	(LOAD_ARGS_TYPES_3): Likewise.

> 	(LOAD_ARGS_TYPES_4): Likewise.

> 	(LOAD_ARGS_TYPES_5): Likewise.

> 	(LOAD_ARGS_TYPES_6): Likewise.

> 	(LOAD_REGS_TYPES_1): Likewise.

> 	(LOAD_REGS_TYPES_2): Likewise.

> 	(LOAD_REGS_TYPES_3): Likewise.

> 	(LOAD_REGS_TYPES_4): Likewise.

> 	(LOAD_REGS_TYPES_5): Likewise.

> 	(LOAD_REGS_TYPES_6): Likewise.

> 	(TYPEFY): New define.

> 	(ARGIFY): Likewise.

> 	(internal_syscall0): Likewise.

> 	(internal_syscall1): Likewise.

> 	(internal_syscall2): Likewise.

> 	(internal_syscall3): Likewise.

> 	(internal_syscall4): Likewise.

> 	(internal_syscall5): Likewise.

> 	(internal_syscall6): Likewise.

> 	* sysdeps/unix/sysv/linux/x86_64/x32/times.c

> 	(INTERNAL_SYSCALL_NCS): Remove define.

> 	(internal_syscall1): Add define.

> ---

>  ChangeLog                                  |  50 ++++++

>  sysdeps/unix/sysv/linux/x86_64/sysdep.h    | 251 ++++++++++++++++-------------

>  sysdeps/unix/sysv/linux/x86_64/x32/times.c |  24 +--

>  3 files changed, 205 insertions(+), 120 deletions(-)

> 

> diff --git a/sysdeps/unix/sysv/linux/x86_64/sysdep.h b/sysdeps/unix/sysv/linux/x86_64/sysdep.h

> index 7b8bd79..6d0a6f4 100644

> --- a/sysdeps/unix/sysv/linux/x86_64/sysdep.h

> +++ b/sysdeps/unix/sysv/linux/x86_64/sysdep.h

> @@ -221,33 +221,148 @@

>  /* Registers clobbered by syscall.  */

>  # define REGISTERS_CLOBBERED_BY_SYSCALL "cc", "r11", "cx"

>  

> -# define INTERNAL_SYSCALL_NCS(name, err, nr, args...) \

> -  ({									      \

> -    unsigned long int resultvar;					      \

> -    LOAD_ARGS_##nr (args)						      \

> -    LOAD_REGS_##nr							      \

> -    asm volatile (							      \

> -    "syscall\n\t"							      \

> -    : "=a" (resultvar)							      \

> -    : "0" (name) ASM_ARGS_##nr : "memory", REGISTERS_CLOBBERED_BY_SYSCALL);   \

> -    (long int) resultvar; })

> -# undef INTERNAL_SYSCALL

> -# define INTERNAL_SYSCALL(name, err, nr, args...) \

> -  INTERNAL_SYSCALL_NCS (__NR_##name, err, nr, ##args)

> -

> -# define INTERNAL_SYSCALL_NCS_TYPES(name, err, nr, args...) \

> -  ({									      \

> -    unsigned long int resultvar;					      \

> -    LOAD_ARGS_TYPES_##nr (args)						      \

> -    LOAD_REGS_TYPES_##nr (args)						      \

> -    asm volatile (							      \

> -    "syscall\n\t"							      \

> -    : "=a" (resultvar)							      \

> -    : "0" (name) ASM_ARGS_##nr : "memory", REGISTERS_CLOBBERED_BY_SYSCALL);   \

> -    (long int) resultvar; })

> -# undef INTERNAL_SYSCALL_TYPES

> -# define INTERNAL_SYSCALL_TYPES(name, err, nr, args...) \

> -  INTERNAL_SYSCALL_NCS_TYPES (__NR_##name, err, nr, ##args)

> +/* Create a variable 'name' based on type 'X' to avoid explicit types.

> +   This is mainly used set use 64-bits arguments in x32.   */

> +#define TYPEFY(X, name) __typeof__ ((X) - (X)) name

> +/* Explicit cast the argument to avoid integer from pointer warning on

> +   x32.  */

> +#define ARGIFY(X) ((__typeof__ ((X) - (X))) (X))

> +

> +#undef INTERNAL_SYSCALL

> +#define INTERNAL_SYSCALL(name, err, nr, args...)			\

> +	internal_syscall##nr (SYS_ify (name), err, args)

> +

> +#undef INTERNAL_SYSCALL_NCS

> +#define INTERNAL_SYSCALL_NCS(number, err, nr, args...)			\

> +	internal_syscall##nr (number, err, args)

> +

> +#undef internal_syscall0

> +#define internal_syscall0(number, err, dummy...)			\

> +({									\

> +    unsigned long int resultvar;					\

> +    asm volatile (							\

> +    "syscall\n\t"							\

> +    : "=a" (resultvar)							\

> +    : "0" (number)							\

> +    : "memory", REGISTERS_CLOBBERED_BY_SYSCALL);			\

> +    (long int) resultvar;						\

> +})

> +

> +#undef internal_syscall1

> +#define internal_syscall1(number, err, arg1)				\

> +({									\

> +    unsigned long int resultvar;					\

> +    TYPEFY (arg1, __arg1) = ARGIFY (arg1);			 	\

> +    register TYPEFY (arg1, _a1) asm ("rdi") = __arg1;			\

> +    asm volatile (							\

> +    "syscall\n\t"							\

> +    : "=a" (resultvar)							\

> +    : "0" (number), "r" (_a1)						\

> +    : "memory", REGISTERS_CLOBBERED_BY_SYSCALL);			\

> +    (long int) resultvar;						\

> +})

> +

> +#undef internal_syscall2

> +#define internal_syscall2(number, err, arg1, arg2)			\

> +({									\

> +    unsigned long int resultvar;					\

> +    TYPEFY (arg2, __arg2) = ARGIFY (arg2);			 	\

> +    TYPEFY (arg1, __arg1) = ARGIFY (arg1);			 	\

> +    register TYPEFY (arg2, _a2) asm ("rsi") = __arg2;			\

> +    register TYPEFY (arg1, _a1) asm ("rdi") = __arg1;			\

> +    asm volatile (							\

> +    "syscall\n\t"							\

> +    : "=a" (resultvar)							\

> +    : "0" (number), "r" (_a1), "r" (_a2)				\

> +    : "memory", REGISTERS_CLOBBERED_BY_SYSCALL);			\

> +    (long int) resultvar;						\

> +})

> +

> +#undef internal_syscall3

> +#define internal_syscall3(number, err, arg1, arg2, arg3)		\

> +({									\

> +    unsigned long int resultvar;					\

> +    TYPEFY (arg3, __arg3) = ARGIFY (arg3);			 	\

> +    TYPEFY (arg2, __arg2) = ARGIFY (arg2);			 	\

> +    TYPEFY (arg1, __arg1) = ARGIFY (arg1);			 	\

> +    register TYPEFY (arg3, _a3) asm ("rdx") = __arg3;			\

> +    register TYPEFY (arg2, _a2) asm ("rsi") = __arg2;			\

> +    register TYPEFY (arg1, _a1) asm ("rdi") = __arg1;			\

> +    asm volatile (							\

> +    "syscall\n\t"							\

> +    : "=a" (resultvar)							\

> +    : "0" (number), "r" (_a1), "r" (_a2), "r" (_a3)			\

> +    : "memory", REGISTERS_CLOBBERED_BY_SYSCALL);			\

> +    (long int) resultvar;						\

> +})

> +

> +#undef internal_syscall4

> +#define internal_syscall4(number, err, arg1, arg2, arg3, arg4)		\

> +({									\

> +    unsigned long int resultvar;					\

> +    TYPEFY (arg4, __arg4) = ARGIFY (arg4);			 	\

> +    TYPEFY (arg3, __arg3) = ARGIFY (arg3);			 	\

> +    TYPEFY (arg2, __arg2) = ARGIFY (arg2);			 	\

> +    TYPEFY (arg1, __arg1) = ARGIFY (arg1);			 	\

> +    register TYPEFY (arg4, _a4) asm ("r10") = __arg4;			\

> +    register TYPEFY (arg3, _a3) asm ("rdx") = __arg3;			\

> +    register TYPEFY (arg2, _a2) asm ("rsi") = __arg2;			\

> +    register TYPEFY (arg1, _a1) asm ("rdi") = __arg1;			\

> +    asm volatile (							\

> +    "syscall\n\t"							\

> +    : "=a" (resultvar)							\

> +    : "0" (number), "r" (_a1), "r" (_a2), "r" (_a3), "r" (_a4)		\

> +    : "memory", REGISTERS_CLOBBERED_BY_SYSCALL);			\

> +    (long int) resultvar;						\

> +})

> +

> +#undef internal_syscall5

> +#define internal_syscall5(number, err, arg1, arg2, arg3, arg4, arg5)	\

> +({									\

> +    unsigned long int resultvar;					\

> +    TYPEFY (arg5, __arg5) = ARGIFY (arg5);			 	\

> +    TYPEFY (arg4, __arg4) = ARGIFY (arg4);			 	\

> +    TYPEFY (arg3, __arg3) = ARGIFY (arg3);			 	\

> +    TYPEFY (arg2, __arg2) = ARGIFY (arg2);			 	\

> +    TYPEFY (arg1, __arg1) = ARGIFY (arg1);			 	\

> +    register TYPEFY (arg5, _a5) asm ("r8") = __arg5;			\

> +    register TYPEFY (arg4, _a4) asm ("r10") = __arg4;			\

> +    register TYPEFY (arg3, _a3) asm ("rdx") = __arg3;			\

> +    register TYPEFY (arg2, _a2) asm ("rsi") = __arg2;			\

> +    register TYPEFY (arg1, _a1) asm ("rdi") = __arg1;			\

> +    asm volatile (							\

> +    "syscall\n\t"							\

> +    : "=a" (resultvar)							\

> +    : "0" (number), "r" (_a1), "r" (_a2), "r" (_a3), "r" (_a4),		\

> +      "r" (_a5)								\

> +    : "memory", REGISTERS_CLOBBERED_BY_SYSCALL);			\

> +    (long int) resultvar;						\

> +})

> +

> +#undef internal_syscall6

> +#define internal_syscall6(number, err, arg1, arg2, arg3, arg4, arg5, arg6) \

> +({									\

> +    unsigned long int resultvar;					\

> +    TYPEFY (arg6, __arg6) = ARGIFY (arg6);			 	\

> +    TYPEFY (arg5, __arg5) = ARGIFY (arg5);			 	\

> +    TYPEFY (arg4, __arg4) = ARGIFY (arg4);			 	\

> +    TYPEFY (arg3, __arg3) = ARGIFY (arg3);			 	\

> +    TYPEFY (arg2, __arg2) = ARGIFY (arg2);			 	\

> +    TYPEFY (arg1, __arg1) = ARGIFY (arg1);			 	\

> +    register TYPEFY (arg6, _a6) asm ("r9") = __arg6;			\

> +    register TYPEFY (arg5, _a5) asm ("r8") = __arg5;			\

> +    register TYPEFY (arg4, _a4) asm ("r10") = __arg4;			\

> +    register TYPEFY (arg3, _a3) asm ("rdx") = __arg3;			\

> +    register TYPEFY (arg2, _a2) asm ("rsi") = __arg2;			\

> +    register TYPEFY (arg1, _a1) asm ("rdi") = __arg1;			\

> +    asm volatile (							\

> +    "syscall\n\t"							\

> +    : "=a" (resultvar)							\

> +    : "0" (number), "r" (_a1), "r" (_a2), "r" (_a3), "r" (_a4),		\

> +      "r" (_a5), "r" (_a6)						\

> +    : "memory", REGISTERS_CLOBBERED_BY_SYSCALL);			\

> +    (long int) resultvar;						\

> +})

>  

>  # undef INTERNAL_SYSCALL_ERROR_P

>  # define INTERNAL_SYSCALL_ERROR_P(val, err) \

> @@ -261,88 +376,6 @@

>  # define HAVE_GETTIMEOFDAY_VSYSCALL     1

>  # define HAVE_GETCPU_VSYSCALL		1

>  

> -# define LOAD_ARGS_0()

> -# define LOAD_REGS_0

> -# define ASM_ARGS_0

> -

> -# define LOAD_ARGS_TYPES_1(t1, a1)					   \

> -  t1 __arg1 = (t1) (a1);						   \

> -  LOAD_ARGS_0 ()

> -# define LOAD_REGS_TYPES_1(t1, a1)					   \

> -  register t1 _a1 asm ("rdi") = __arg1;					   \

> -  LOAD_REGS_0

> -# define ASM_ARGS_1	ASM_ARGS_0, "r" (_a1)

> -# define LOAD_ARGS_1(a1)						   \

> -  LOAD_ARGS_TYPES_1 (long int, a1)

> -# define LOAD_REGS_1							   \

> -  LOAD_REGS_TYPES_1 (long int, a1)

> -

> -# define LOAD_ARGS_TYPES_2(t1, a1, t2, a2)				   \

> -  t2 __arg2 = (t2) (a2);						   \

> -  LOAD_ARGS_TYPES_1 (t1, a1)

> -# define LOAD_REGS_TYPES_2(t1, a1, t2, a2)				   \

> -  register t2 _a2 asm ("rsi") = __arg2;					   \

> -  LOAD_REGS_TYPES_1(t1, a1)

> -# define ASM_ARGS_2	ASM_ARGS_1, "r" (_a2)

> -# define LOAD_ARGS_2(a1, a2)						   \

> -  LOAD_ARGS_TYPES_2 (long int, a1, long int, a2)

> -# define LOAD_REGS_2							   \

> -  LOAD_REGS_TYPES_2 (long int, a1, long int, a2)

> -

> -# define LOAD_ARGS_TYPES_3(t1, a1, t2, a2, t3, a3)			   \

> -  t3 __arg3 = (t3) (a3);						   \

> -  LOAD_ARGS_TYPES_2 (t1, a1, t2, a2)

> -# define LOAD_REGS_TYPES_3(t1, a1, t2, a2, t3, a3)			   \

> -  register t3 _a3 asm ("rdx") = __arg3;					   \

> -  LOAD_REGS_TYPES_2(t1, a1, t2, a2)

> -# define ASM_ARGS_3	ASM_ARGS_2, "r" (_a3)

> -# define LOAD_ARGS_3(a1, a2, a3)					   \

> -  LOAD_ARGS_TYPES_3 (long int, a1, long int, a2, long int, a3)

> -# define LOAD_REGS_3							   \

> -  LOAD_REGS_TYPES_3 (long int, a1, long int, a2, long int, a3)

> -

> -# define LOAD_ARGS_TYPES_4(t1, a1, t2, a2, t3, a3, t4, a4)		   \

> -  t4 __arg4 = (t4) (a4);						   \

> -  LOAD_ARGS_TYPES_3 (t1, a1, t2, a2, t3, a3)

> -# define LOAD_REGS_TYPES_4(t1, a1, t2, a2, t3, a3, t4, a4)		   \

> -  register t4 _a4 asm ("r10") = __arg4;					   \

> -  LOAD_REGS_TYPES_3(t1, a2, t2, a2, t3, a3)

> -# define ASM_ARGS_4	ASM_ARGS_3, "r" (_a4)

> -# define LOAD_ARGS_4(a1, a2, a3, a4)					   \

> -  LOAD_ARGS_TYPES_4 (long int, a1, long int, a2, long int, a3,		   \

> -		     long int, a4)

> -# define LOAD_REGS_4							   \

> -  LOAD_REGS_TYPES_4 (long int, a1, long int, a2, long int, a3,		   \

> -		     long int, a4)

> -

> -# define LOAD_ARGS_TYPES_5(t1, a1, t2, a2, t3, a3, t4, a4, t5, a5)	   \

> -  t5 __arg5 = (t5) (a5);						   \

> -  LOAD_ARGS_TYPES_4 (t1, a1, t2, a2, t3, a3, t4, a4)

> -# define LOAD_REGS_TYPES_5(t1, a1, t2, a2, t3, a3, t4, a4, t5, a5)	   \

> -  register t5 _a5 asm ("r8") = __arg5;					   \

> -  LOAD_REGS_TYPES_4 (t1, a1, t2, a2, t3, a3, t4, a4)

> -# define ASM_ARGS_5	ASM_ARGS_4, "r" (_a5)

> -# define LOAD_ARGS_5(a1, a2, a3, a4, a5)				   \

> -  LOAD_ARGS_TYPES_5 (long int, a1, long int, a2, long int, a3,		   \

> -		     long int, a4, long int, a5)

> -# define LOAD_REGS_5							   \

> -  LOAD_REGS_TYPES_5 (long int, a1, long int, a2, long int, a3,		   \

> -		     long int, a4, long int, a5)

> -

> -# define LOAD_ARGS_TYPES_6(t1, a1, t2, a2, t3, a3, t4, a4, t5, a5, t6, a6) \

> -  t6 __arg6 = (t6) (a6);						   \

> -  LOAD_ARGS_TYPES_5 (t1, a1, t2, a2, t3, a3, t4, a4, t5, a5)

> -# define LOAD_REGS_TYPES_6(t1, a1, t2, a2, t3, a3, t4, a4, t5, a5, t6, a6) \

> -  register t6 _a6 asm ("r9") = __arg6;					   \

> -  LOAD_REGS_TYPES_5 (t1, a1, t2, a2, t3, a3, t4, a4, t5, a5)

> -# define ASM_ARGS_6	ASM_ARGS_5, "r" (_a6)

> -# define LOAD_ARGS_6(a1, a2, a3, a4, a5, a6)				   \

> -  LOAD_ARGS_TYPES_6 (long int, a1, long int, a2, long int, a3,		   \

> -		     long int, a4, long int, a5, long int, a6)

> -# define LOAD_REGS_6							   \

> -  LOAD_REGS_TYPES_6 (long int, a1, long int, a2, long int, a3,		   \

> -		     long int, a4, long int, a5, long int, a6)

> -

>  #endif	/* __ASSEMBLER__ */

>  

>  

> diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/times.c b/sysdeps/unix/sysv/linux/x86_64/x32/times.c

> index d56106e..8763047 100644

> --- a/sysdeps/unix/sysv/linux/x86_64/x32/times.c

> +++ b/sysdeps/unix/sysv/linux/x86_64/x32/times.c

> @@ -19,17 +19,19 @@

>  #include <sysdep.h>

>  

>  /* Linux times system call returns 64-bit integer.  */

> -#undef INTERNAL_SYSCALL_NCS

> -#define INTERNAL_SYSCALL_NCS(name, err, nr, args...) \

> -  ({									      \

> -    unsigned long long int resultvar;					      \

> -    LOAD_ARGS_##nr (args)						      \

> -    LOAD_REGS_##nr							      \

> -    asm volatile (							      \

> -    "syscall\n\t"							      \

> -    : "=a" (resultvar)							      \

> -    : "0" (name) ASM_ARGS_##nr : "memory", REGISTERS_CLOBBERED_BY_SYSCALL);   \

> -    (long long int) resultvar; })

> +#undef internal_syscall1

> +#define internal_syscall1(number, err, arg1)				\

> +({									\

> +    unsigned long long int resultvar;					\

> +    TYPEFY (arg1, __arg1) = ARGIFY (arg1);			 	\

> +    register TYPEFY (arg1, _a1) asm ("rdi") = __arg1;			\

> +    asm volatile (							\

> +    "syscall\n\t"							\

> +    : "=a" (resultvar)							\

> +    : "0" (number), "r" (_a1)						\

> +    : "memory", REGISTERS_CLOBBERED_BY_SYSCALL);			\

> +    (long long int) resultvar;						\

> +})

>  

>  #undef INTERNAL_SYSCALL_ERROR_P

>  #define INTERNAL_SYSCALL_ERROR_P(val, err) \

>
Florian Weimer June 29, 2017, 6:50 p.m. UTC | #2
On 06/29/2017 04:15 PM, Adhemerval Zanella wrote:
> +/* Create a variable 'name' based on type 'X' to avoid explicit types.

> +   This is mainly used set use 64-bits arguments in x32.   */

> +#define TYPEFY(X, name) __typeof__ ((X) - (X)) name

> +/* Explicit cast the argument to avoid integer from pointer warning on

> +   x32.  */

> +#define ARGIFY(X) ((__typeof__ ((X) - (X))) (X))


I think cast_to_integer was added for this purpose.

Thanks,
Florian
Adhemerval Zanella Netto June 30, 2017, 3:03 p.m. UTC | #3
On 29/06/2017 15:50, Florian Weimer wrote:
> On 06/29/2017 04:15 PM, Adhemerval Zanella wrote:

>> +/* Create a variable 'name' based on type 'X' to avoid explicit types.

>> +   This is mainly used set use 64-bits arguments in x32.   */

>> +#define TYPEFY(X, name) __typeof__ ((X) - (X)) name

>> +/* Explicit cast the argument to avoid integer from pointer warning on

>> +   x32.  */

>> +#define ARGIFY(X) ((__typeof__ ((X) - (X))) (X))

> 

> I think cast_to_integer was added for this purpose.


The 'cast_to_integer' macro was added after my initial (I based the ARGIFY
macro on the mips64n32 one) and checking it by replacing ARGIGY with 
'cast_to_integer' I see:

---
gconv_cache.c: In function ‘__gconv_load_cache’:
../include/libc-pointer-arith.h:34:45: error: cast specifies array type
   __integer_if_pointer_type_sub(__typeof__ ((__typeof__ (expr)) 0), \
                                             ^
../include/libc-pointer-arith.h:29:39: note: in definition of macro ‘__integer_if_pointer_type_sub’
   __typeof__ (*(0 ? (__typeof__ (0 ? (T *) 0 : (void *) (P))) 0 \
                                       ^
../include/libc-pointer-arith.h:38:33: note: in expansion of macro ‘__integer_if_pointer_type’
 # define cast_to_integer(val) ((__integer_if_pointer_type (val)) (val))
                                 ^~~~~~~~~~~~~~~~~~~~~~~~~
../sysdeps/unix/sysv/linux/x86_64/sysdep.h:284:29: note: in expansion of macro ‘cast_to_integer’
     TYPEFY (arg1, __arg1) = cast_to_integer (arg1);    \
                             ^~~~~~~~~~~~~~~
../sysdeps/unix/sysv/linux/x86_64/sysdep.h:230:2: note: in expansion of macro ‘internal_syscall3’
  internal_syscall##nr (SYS_ify (name), err, args)
  ^~~~~~~~~~~~~~~~
../sysdeps/unix/sysv/linux/x86_64/sysdep.h:196:35: note: in expansion of macro ‘INTERNAL_SYSCALL’
     unsigned long int resultvar = INTERNAL_SYSCALL (name, , nr, args);       \
                                   ^~~~~~~~~~~~~~~~
../sysdeps/unix/sysv/linux/not-cancel.h:31:4: note: in expansion of macro ‘INLINE_SYSCALL’
    INLINE_SYSCALL (open, 3, name, flags, mode)
---

And I recall this was one the issue I had when creating this patch. Using compound
literal on __typeof__ cast did not help due we build with -Wwrite-strings it and
in turn it enables -Wdiscarded-array-qualifiers.  This triggers a 'pointer to
array loses qualifier', because constness type is propagate.

So to actually use cast_to_integer workable on char array (and on other arrays
as well) one solution is to incorporate the arithmetic promotion used on 
mips64n32 sysdep and also on this patch:

---
/* Type cast using arithmetic promotion.  It also remove l-value-constness
   when using char arrays on cast_to_interger (for instance
   cast_to_interger ("...") will not trigger a 'pointer to array loses
   qualifier' warning due -Wdiscarded-array-qualifiers from -Wwrite-strings.
 */
# define __typeof_arith_promote(T) __typeof__((T) - (T))

/* 1 if 'type' is a pointer type, 0 otherwise.  */
# define __pointer_type(type) (__builtin_classify_type ((type) 0) == 5)

/* intptr_t if P is true, or T if P is false.  */
# define __integer_if_pointer_type_sub(T, P) \
  __typeof__ (*(0 ? (__typeof__ (0 ? (T *) 0: (void *) (P))) 0 \
                  : (__typeof__ (0 ? (intptr_t *) 0: (void *) (!(P)))) 0))

/* intptr_t if EXPR has a pointer type, or the type of EXPR otherwise.  */
# define __integer_if_pointer_type(expr) \
  __integer_if_pointer_type_sub(__typeof__ ((__typeof_arith_promote (expr)) 0), \
                                __pointer_type (__typeof_arith_promote (expr)))

/* Cast an integer or a pointer VAL to integer with proper type.  */
# define cast_to_integer(val) ((__integer_if_pointer_type (val)) (val))
---

I am not sure how safe is the arithmetic promotion in the all the possible
cases where one could use cast_to_integer, however current cases on atomic
and syscall usage should be safe (make check shows no regression on
x86_64{-x32} with the pread auto-generate removal applied, so they use the 
default Linux implementation. If you think it is worth I can resend with the
libc-pointer-arith.h modification.
H.J. Lu July 1, 2017, 4:53 p.m. UTC | #4
On Tue, May 23, 2017 at 11:25 AM, Adhemerval Zanella
<adhemerval.zanella@linaro.org> wrote:
> From: Adhemerval Zanella <adhemerval.zanella@linaro.com>

>

> The problem for x32 is the {INTERNAL,INLINE}_SYSCALL C macros explicit

> cast the arguments to 'long int', thus passing as 32 bits arguments

> that should be passed to 64 bits.

>

> Previous x32 implementation uses the auto-generated syscalls from

> assembly macros (syscalls.list), so the {INTERNAL,INLINE}_SYSCALL

> macros are never used with 64 bit argument in x32 (which are

> internally broken for this ILP).

>

> To fix it I used a strategy similar to MIPS64n32 (although both

> ABI differs for some syscalls on how top pass 64-bits arguments)

> where argument types for kernel call are defined using GCC extension

> 'typeof' with a arithmetic operation.  This allows 64-bits arguments

> to be defined while 32-bits argument will still passed as 32-bits.

>

> I also cleanup the {INLINE,INTERNAL}_SYSCALL definition by defining

> 'inline_syscallX' instead of constructing the argument passing using

> macros (it adds some readability) and removed the ununsed

> INTERNAL_SYSCALL_NCS_TYPES define (since the patch idea is exactly to

> avoid requiric explicit types passing).

>

> Tested on x86_64 and x32.

>

>         * sysdeps/unix/sysv/linux/x86_64/sysdep.h

>         (INTERNAL_SYSCALL_NCS_TYPES): Remove define.

>         (LOAD_ARGS_0): Likewise.

>         (LOAD_ARGS_1): Likewise.

>         (LOAD_ARGS_2): Likewise.

>         (LOAD_ARGS_3): Likewise.

>         (LOAD_ARGS_4): Likewise.

>         (LOAD_ARGS_5): Likewise.

>         (LOAD_ARGS_6): Likewise.

>         (LOAD_REGS_0): Likewise.

>         (LOAD_REGS_1): Likewise.

>         (LOAD_REGS_2): Likewise.

>         (LOAD_REGS_3): Likewise.

>         (LOAD_REGS_4): Likewise.

>         (LOAD_REGS_5): Likewise.

>         (LOAD_REGS_6): Likewise.

>         (ASM_ARGS_0): Likewise.

>         (ASM_ARGS_1): Likewise.

>         (ASM_ARGS_2): Likewise.

>         (ASM_ARGS_3): Likewise.

>         (ASM_ARGS_4): Likewise.

>         (ASM_ARGS_5): Likewise.

>         (ASM_ARGS_6): Likewise.

>         (LOAD_ARGS_TYPES_1): Likewise.

>         (LOAD_ARGS_TYPES_2): Likewise.

>         (LOAD_ARGS_TYPES_3): Likewise.

>         (LOAD_ARGS_TYPES_4): Likewise.

>         (LOAD_ARGS_TYPES_5): Likewise.

>         (LOAD_ARGS_TYPES_6): Likewise.

>         (LOAD_REGS_TYPES_1): Likewise.

>         (LOAD_REGS_TYPES_2): Likewise.

>         (LOAD_REGS_TYPES_3): Likewise.

>         (LOAD_REGS_TYPES_4): Likewise.

>         (LOAD_REGS_TYPES_5): Likewise.

>         (LOAD_REGS_TYPES_6): Likewise.

>         (TYPEFY): New define.

>         (ARGIFY): Likewise.

>         (internal_syscall0): Likewise.

>         (internal_syscall1): Likewise.

>         (internal_syscall2): Likewise.

>         (internal_syscall3): Likewise.

>         (internal_syscall4): Likewise.

>         (internal_syscall5): Likewise.

>         (internal_syscall6): Likewise.

>         * sysdeps/unix/sysv/linux/x86_64/x32/times.c

>         (INTERNAL_SYSCALL_NCS): Remove define.

>         (internal_syscall1): Add define.

> ---

>  ChangeLog                                  |  50 ++++++

>  sysdeps/unix/sysv/linux/x86_64/sysdep.h    | 251 ++++++++++++++++-------------

>  sysdeps/unix/sysv/linux/x86_64/x32/times.c |  24 +--

>  3 files changed, 205 insertions(+), 120 deletions(-)

>

> diff --git a/sysdeps/unix/sysv/linux/x86_64/sysdep.h b/sysdeps/unix/sysv/linux/x86_64/sysdep.h

> index 7b8bd79..6d0a6f4 100644

> --- a/sysdeps/unix/sysv/linux/x86_64/sysdep.h

> +++ b/sysdeps/unix/sysv/linux/x86_64/sysdep.h

> @@ -221,33 +221,148 @@

>  /* Registers clobbered by syscall.  */

>  # define REGISTERS_CLOBBERED_BY_SYSCALL "cc", "r11", "cx"

>

> -# define INTERNAL_SYSCALL_NCS(name, err, nr, args...) \

> -  ({                                                                         \

> -    unsigned long int resultvar;                                             \

> -    LOAD_ARGS_##nr (args)                                                    \

> -    LOAD_REGS_##nr                                                           \

> -    asm volatile (                                                           \

> -    "syscall\n\t"                                                            \

> -    : "=a" (resultvar)                                                       \

> -    : "0" (name) ASM_ARGS_##nr : "memory", REGISTERS_CLOBBERED_BY_SYSCALL);   \

> -    (long int) resultvar; })

> -# undef INTERNAL_SYSCALL

> -# define INTERNAL_SYSCALL(name, err, nr, args...) \

> -  INTERNAL_SYSCALL_NCS (__NR_##name, err, nr, ##args)

> -

> -# define INTERNAL_SYSCALL_NCS_TYPES(name, err, nr, args...) \

> -  ({                                                                         \

> -    unsigned long int resultvar;                                             \

> -    LOAD_ARGS_TYPES_##nr (args)                                                      \

> -    LOAD_REGS_TYPES_##nr (args)                                                      \

> -    asm volatile (                                                           \

> -    "syscall\n\t"                                                            \

> -    : "=a" (resultvar)                                                       \

> -    : "0" (name) ASM_ARGS_##nr : "memory", REGISTERS_CLOBBERED_BY_SYSCALL);   \

> -    (long int) resultvar; })

> -# undef INTERNAL_SYSCALL_TYPES

> -# define INTERNAL_SYSCALL_TYPES(name, err, nr, args...) \

> -  INTERNAL_SYSCALL_NCS_TYPES (__NR_##name, err, nr, ##args)

> +/* Create a variable 'name' based on type 'X' to avoid explicit types.

> +   This is mainly used set use 64-bits arguments in x32.   */

> +#define TYPEFY(X, name) __typeof__ ((X) - (X)) name

> +/* Explicit cast the argument to avoid integer from pointer warning on

> +   x32.  */

> +#define ARGIFY(X) ((__typeof__ ((X) - (X))) (X))

> +


I am a little bit concerned about this.  The current macros cast to long int
by default on purpose.  64-bit return and arguments are treated as
special cases.   With your change, this code in loadlocale.c:

         if (filedata != NULL)
            {
              off_t to_read = st.st_size;
              ssize_t nread;
              char *p = (char *) filedata;
              while (to_read > 0)
                {
                  nread = read_not_cancel (fd, p, to_read);
                  if (__builtin_expect (nread, 1) <= 0)
                    {
                      free (filedata);
                      if (nread == 0)
                        __set_errno (EINVAL); /* Bizarreness going on.  */
                      goto puntfd;
                    }
                  p += nread;

is generated differently.  On x32, ssize_t is 32 bits and offset is 64 bits.
Before your patch, to_read is passed as 32 bit value.  With your change,
__typeof__ ((X) - (X)) turns to_read into 64 bits.  It may be OK for this
particular case.  But I am not certain that your change is 100% safe in
all cases.

H.J.
Adhemerval Zanella Netto July 3, 2017, 11:52 a.m. UTC | #5
On 01/07/2017 13:53, H.J. Lu wrote:
> On Tue, May 23, 2017 at 11:25 AM, Adhemerval Zanella

> <adhemerval.zanella@linaro.org> wrote:

>> From: Adhemerval Zanella <adhemerval.zanella@linaro.com>

>>

>> The problem for x32 is the {INTERNAL,INLINE}_SYSCALL C macros explicit

>> cast the arguments to 'long int', thus passing as 32 bits arguments

>> that should be passed to 64 bits.

>>

>> Previous x32 implementation uses the auto-generated syscalls from

>> assembly macros (syscalls.list), so the {INTERNAL,INLINE}_SYSCALL

>> macros are never used with 64 bit argument in x32 (which are

>> internally broken for this ILP).

>>

>> To fix it I used a strategy similar to MIPS64n32 (although both

>> ABI differs for some syscalls on how top pass 64-bits arguments)

>> where argument types for kernel call are defined using GCC extension

>> 'typeof' with a arithmetic operation.  This allows 64-bits arguments

>> to be defined while 32-bits argument will still passed as 32-bits.

>>

>> I also cleanup the {INLINE,INTERNAL}_SYSCALL definition by defining

>> 'inline_syscallX' instead of constructing the argument passing using

>> macros (it adds some readability) and removed the ununsed

>> INTERNAL_SYSCALL_NCS_TYPES define (since the patch idea is exactly to

>> avoid requiric explicit types passing).

>>

>> Tested on x86_64 and x32.

>>

>>         * sysdeps/unix/sysv/linux/x86_64/sysdep.h

>>         (INTERNAL_SYSCALL_NCS_TYPES): Remove define.

>>         (LOAD_ARGS_0): Likewise.

>>         (LOAD_ARGS_1): Likewise.

>>         (LOAD_ARGS_2): Likewise.

>>         (LOAD_ARGS_3): Likewise.

>>         (LOAD_ARGS_4): Likewise.

>>         (LOAD_ARGS_5): Likewise.

>>         (LOAD_ARGS_6): Likewise.

>>         (LOAD_REGS_0): Likewise.

>>         (LOAD_REGS_1): Likewise.

>>         (LOAD_REGS_2): Likewise.

>>         (LOAD_REGS_3): Likewise.

>>         (LOAD_REGS_4): Likewise.

>>         (LOAD_REGS_5): Likewise.

>>         (LOAD_REGS_6): Likewise.

>>         (ASM_ARGS_0): Likewise.

>>         (ASM_ARGS_1): Likewise.

>>         (ASM_ARGS_2): Likewise.

>>         (ASM_ARGS_3): Likewise.

>>         (ASM_ARGS_4): Likewise.

>>         (ASM_ARGS_5): Likewise.

>>         (ASM_ARGS_6): Likewise.

>>         (LOAD_ARGS_TYPES_1): Likewise.

>>         (LOAD_ARGS_TYPES_2): Likewise.

>>         (LOAD_ARGS_TYPES_3): Likewise.

>>         (LOAD_ARGS_TYPES_4): Likewise.

>>         (LOAD_ARGS_TYPES_5): Likewise.

>>         (LOAD_ARGS_TYPES_6): Likewise.

>>         (LOAD_REGS_TYPES_1): Likewise.

>>         (LOAD_REGS_TYPES_2): Likewise.

>>         (LOAD_REGS_TYPES_3): Likewise.

>>         (LOAD_REGS_TYPES_4): Likewise.

>>         (LOAD_REGS_TYPES_5): Likewise.

>>         (LOAD_REGS_TYPES_6): Likewise.

>>         (TYPEFY): New define.

>>         (ARGIFY): Likewise.

>>         (internal_syscall0): Likewise.

>>         (internal_syscall1): Likewise.

>>         (internal_syscall2): Likewise.

>>         (internal_syscall3): Likewise.

>>         (internal_syscall4): Likewise.

>>         (internal_syscall5): Likewise.

>>         (internal_syscall6): Likewise.

>>         * sysdeps/unix/sysv/linux/x86_64/x32/times.c

>>         (INTERNAL_SYSCALL_NCS): Remove define.

>>         (internal_syscall1): Add define.

>> ---

>>  ChangeLog                                  |  50 ++++++

>>  sysdeps/unix/sysv/linux/x86_64/sysdep.h    | 251 ++++++++++++++++-------------

>>  sysdeps/unix/sysv/linux/x86_64/x32/times.c |  24 +--

>>  3 files changed, 205 insertions(+), 120 deletions(-)

>>

>> diff --git a/sysdeps/unix/sysv/linux/x86_64/sysdep.h b/sysdeps/unix/sysv/linux/x86_64/sysdep.h

>> index 7b8bd79..6d0a6f4 100644

>> --- a/sysdeps/unix/sysv/linux/x86_64/sysdep.h

>> +++ b/sysdeps/unix/sysv/linux/x86_64/sysdep.h

>> @@ -221,33 +221,148 @@

>>  /* Registers clobbered by syscall.  */

>>  # define REGISTERS_CLOBBERED_BY_SYSCALL "cc", "r11", "cx"

>>

>> -# define INTERNAL_SYSCALL_NCS(name, err, nr, args...) \

>> -  ({                                                                         \

>> -    unsigned long int resultvar;                                             \

>> -    LOAD_ARGS_##nr (args)                                                    \

>> -    LOAD_REGS_##nr                                                           \

>> -    asm volatile (                                                           \

>> -    "syscall\n\t"                                                            \

>> -    : "=a" (resultvar)                                                       \

>> -    : "0" (name) ASM_ARGS_##nr : "memory", REGISTERS_CLOBBERED_BY_SYSCALL);   \

>> -    (long int) resultvar; })

>> -# undef INTERNAL_SYSCALL

>> -# define INTERNAL_SYSCALL(name, err, nr, args...) \

>> -  INTERNAL_SYSCALL_NCS (__NR_##name, err, nr, ##args)

>> -

>> -# define INTERNAL_SYSCALL_NCS_TYPES(name, err, nr, args...) \

>> -  ({                                                                         \

>> -    unsigned long int resultvar;                                             \

>> -    LOAD_ARGS_TYPES_##nr (args)                                                      \

>> -    LOAD_REGS_TYPES_##nr (args)                                                      \

>> -    asm volatile (                                                           \

>> -    "syscall\n\t"                                                            \

>> -    : "=a" (resultvar)                                                       \

>> -    : "0" (name) ASM_ARGS_##nr : "memory", REGISTERS_CLOBBERED_BY_SYSCALL);   \

>> -    (long int) resultvar; })

>> -# undef INTERNAL_SYSCALL_TYPES

>> -# define INTERNAL_SYSCALL_TYPES(name, err, nr, args...) \

>> -  INTERNAL_SYSCALL_NCS_TYPES (__NR_##name, err, nr, ##args)

>> +/* Create a variable 'name' based on type 'X' to avoid explicit types.

>> +   This is mainly used set use 64-bits arguments in x32.   */

>> +#define TYPEFY(X, name) __typeof__ ((X) - (X)) name

>> +/* Explicit cast the argument to avoid integer from pointer warning on

>> +   x32.  */

>> +#define ARGIFY(X) ((__typeof__ ((X) - (X))) (X))

>> +

> 

> I am a little bit concerned about this.  The current macros cast to long int

> by default on purpose.  64-bit return and arguments are treated as

> special cases.   With your change, this code in loadlocale.c:

> 

>          if (filedata != NULL)

>             {

>               off_t to_read = st.st_size;

>               ssize_t nread;

>               char *p = (char *) filedata;

>               while (to_read > 0)

>                 {

>                   nread = read_not_cancel (fd, p, to_read);

>                   if (__builtin_expect (nread, 1) <= 0)

>                     {

>                       free (filedata);

>                       if (nread == 0)

>                         __set_errno (EINVAL); /* Bizarreness going on.  */

>                       goto puntfd;

>                     }

>                   p += nread;

> 

> is generated differently.  On x32, ssize_t is 32 bits and offset is 64 bits.

> Before your patch, to_read is passed as 32 bit value.  With your change,

> __typeof__ ((X) - (X)) turns to_read into 64 bits.  It may be OK for this

> particular case.  But I am not certain that your change is 100% safe in

> all cases.


I think the problem is we define 'read_not_cancel' as a macro rather than
an static inline with expected arguments types.  For a QoI I think creating
wrappers around it would be better.

I would like to make the syscall internal macros to work seamlessly across 
all architectures and avoid to create specialized assembly macros for 
specific syscalls (such as lseek{64} for x32 witch I think it is not 
avoidable). Also x32 is the only architecture afaik preventing the 
syscall-cancel.h cleanup currently.
H.J. Lu July 3, 2017, 7:44 p.m. UTC | #6
On Mon, Jul 3, 2017 at 4:52 AM, Adhemerval Zanella
<adhemerval.zanella@linaro.org> wrote:
>

>

> On 01/07/2017 13:53, H.J. Lu wrote:

>> On Tue, May 23, 2017 at 11:25 AM, Adhemerval Zanella

>> <adhemerval.zanella@linaro.org> wrote:

>>> From: Adhemerval Zanella <adhemerval.zanella@linaro.com>

>>>

>>> The problem for x32 is the {INTERNAL,INLINE}_SYSCALL C macros explicit

>>> cast the arguments to 'long int', thus passing as 32 bits arguments

>>> that should be passed to 64 bits.

>>>

>>> Previous x32 implementation uses the auto-generated syscalls from

>>> assembly macros (syscalls.list), so the {INTERNAL,INLINE}_SYSCALL

>>> macros are never used with 64 bit argument in x32 (which are

>>> internally broken for this ILP).

>>>

>>> To fix it I used a strategy similar to MIPS64n32 (although both

>>> ABI differs for some syscalls on how top pass 64-bits arguments)

>>> where argument types for kernel call are defined using GCC extension

>>> 'typeof' with a arithmetic operation.  This allows 64-bits arguments

>>> to be defined while 32-bits argument will still passed as 32-bits.

>>>

>>> I also cleanup the {INLINE,INTERNAL}_SYSCALL definition by defining

>>> 'inline_syscallX' instead of constructing the argument passing using

>>> macros (it adds some readability) and removed the ununsed

>>> INTERNAL_SYSCALL_NCS_TYPES define (since the patch idea is exactly to

>>> avoid requiric explicit types passing).

>>>

>>> Tested on x86_64 and x32.

>>>

>>>         * sysdeps/unix/sysv/linux/x86_64/sysdep.h

>>>         (INTERNAL_SYSCALL_NCS_TYPES): Remove define.

>>>         (LOAD_ARGS_0): Likewise.

>>>         (LOAD_ARGS_1): Likewise.

>>>         (LOAD_ARGS_2): Likewise.

>>>         (LOAD_ARGS_3): Likewise.

>>>         (LOAD_ARGS_4): Likewise.

>>>         (LOAD_ARGS_5): Likewise.

>>>         (LOAD_ARGS_6): Likewise.

>>>         (LOAD_REGS_0): Likewise.

>>>         (LOAD_REGS_1): Likewise.

>>>         (LOAD_REGS_2): Likewise.

>>>         (LOAD_REGS_3): Likewise.

>>>         (LOAD_REGS_4): Likewise.

>>>         (LOAD_REGS_5): Likewise.

>>>         (LOAD_REGS_6): Likewise.

>>>         (ASM_ARGS_0): Likewise.

>>>         (ASM_ARGS_1): Likewise.

>>>         (ASM_ARGS_2): Likewise.

>>>         (ASM_ARGS_3): Likewise.

>>>         (ASM_ARGS_4): Likewise.

>>>         (ASM_ARGS_5): Likewise.

>>>         (ASM_ARGS_6): Likewise.

>>>         (LOAD_ARGS_TYPES_1): Likewise.

>>>         (LOAD_ARGS_TYPES_2): Likewise.

>>>         (LOAD_ARGS_TYPES_3): Likewise.

>>>         (LOAD_ARGS_TYPES_4): Likewise.

>>>         (LOAD_ARGS_TYPES_5): Likewise.

>>>         (LOAD_ARGS_TYPES_6): Likewise.

>>>         (LOAD_REGS_TYPES_1): Likewise.

>>>         (LOAD_REGS_TYPES_2): Likewise.

>>>         (LOAD_REGS_TYPES_3): Likewise.

>>>         (LOAD_REGS_TYPES_4): Likewise.

>>>         (LOAD_REGS_TYPES_5): Likewise.

>>>         (LOAD_REGS_TYPES_6): Likewise.

>>>         (TYPEFY): New define.

>>>         (ARGIFY): Likewise.

>>>         (internal_syscall0): Likewise.

>>>         (internal_syscall1): Likewise.

>>>         (internal_syscall2): Likewise.

>>>         (internal_syscall3): Likewise.

>>>         (internal_syscall4): Likewise.

>>>         (internal_syscall5): Likewise.

>>>         (internal_syscall6): Likewise.

>>>         * sysdeps/unix/sysv/linux/x86_64/x32/times.c

>>>         (INTERNAL_SYSCALL_NCS): Remove define.

>>>         (internal_syscall1): Add define.

>>> ---

>>>  ChangeLog                                  |  50 ++++++

>>>  sysdeps/unix/sysv/linux/x86_64/sysdep.h    | 251 ++++++++++++++++-------------

>>>  sysdeps/unix/sysv/linux/x86_64/x32/times.c |  24 +--

>>>  3 files changed, 205 insertions(+), 120 deletions(-)

>>>

>>> diff --git a/sysdeps/unix/sysv/linux/x86_64/sysdep.h b/sysdeps/unix/sysv/linux/x86_64/sysdep.h

>>> index 7b8bd79..6d0a6f4 100644

>>> --- a/sysdeps/unix/sysv/linux/x86_64/sysdep.h

>>> +++ b/sysdeps/unix/sysv/linux/x86_64/sysdep.h

>>> @@ -221,33 +221,148 @@

>>>  /* Registers clobbered by syscall.  */

>>>  # define REGISTERS_CLOBBERED_BY_SYSCALL "cc", "r11", "cx"

>>>

>>> -# define INTERNAL_SYSCALL_NCS(name, err, nr, args...) \

>>> -  ({                                                                         \

>>> -    unsigned long int resultvar;                                             \

>>> -    LOAD_ARGS_##nr (args)                                                    \

>>> -    LOAD_REGS_##nr                                                           \

>>> -    asm volatile (                                                           \

>>> -    "syscall\n\t"                                                            \

>>> -    : "=a" (resultvar)                                                       \

>>> -    : "0" (name) ASM_ARGS_##nr : "memory", REGISTERS_CLOBBERED_BY_SYSCALL);   \

>>> -    (long int) resultvar; })

>>> -# undef INTERNAL_SYSCALL

>>> -# define INTERNAL_SYSCALL(name, err, nr, args...) \

>>> -  INTERNAL_SYSCALL_NCS (__NR_##name, err, nr, ##args)

>>> -

>>> -# define INTERNAL_SYSCALL_NCS_TYPES(name, err, nr, args...) \

>>> -  ({                                                                         \

>>> -    unsigned long int resultvar;                                             \

>>> -    LOAD_ARGS_TYPES_##nr (args)                                                      \

>>> -    LOAD_REGS_TYPES_##nr (args)                                                      \

>>> -    asm volatile (                                                           \

>>> -    "syscall\n\t"                                                            \

>>> -    : "=a" (resultvar)                                                       \

>>> -    : "0" (name) ASM_ARGS_##nr : "memory", REGISTERS_CLOBBERED_BY_SYSCALL);   \

>>> -    (long int) resultvar; })

>>> -# undef INTERNAL_SYSCALL_TYPES

>>> -# define INTERNAL_SYSCALL_TYPES(name, err, nr, args...) \

>>> -  INTERNAL_SYSCALL_NCS_TYPES (__NR_##name, err, nr, ##args)

>>> +/* Create a variable 'name' based on type 'X' to avoid explicit types.

>>> +   This is mainly used set use 64-bits arguments in x32.   */

>>> +#define TYPEFY(X, name) __typeof__ ((X) - (X)) name

>>> +/* Explicit cast the argument to avoid integer from pointer warning on

>>> +   x32.  */

>>> +#define ARGIFY(X) ((__typeof__ ((X) - (X))) (X))

>>> +

>>

>> I am a little bit concerned about this.  The current macros cast to long int

>> by default on purpose.  64-bit return and arguments are treated as

>> special cases.   With your change, this code in loadlocale.c:

>>

>>          if (filedata != NULL)

>>             {

>>               off_t to_read = st.st_size;

>>               ssize_t nread;

>>               char *p = (char *) filedata;

>>               while (to_read > 0)

>>                 {

>>                   nread = read_not_cancel (fd, p, to_read);

>>                   if (__builtin_expect (nread, 1) <= 0)

>>                     {

>>                       free (filedata);

>>                       if (nread == 0)

>>                         __set_errno (EINVAL); /* Bizarreness going on.  */

>>                       goto puntfd;

>>                     }

>>                   p += nread;

>>

>> is generated differently.  On x32, ssize_t is 32 bits and offset is 64 bits.

>> Before your patch, to_read is passed as 32 bit value.  With your change,

>> __typeof__ ((X) - (X)) turns to_read into 64 bits.  It may be OK for this

>> particular case.  But I am not certain that your change is 100% safe in

>> all cases.

>

> I think the problem is we define 'read_not_cancel' as a macro rather than

> an static inline with expected arguments types.  For a QoI I think creating

> wrappers around it would be better.


That is fine with me.

> I would like to make the syscall internal macros to work seamlessly across

> all architectures and avoid to create specialized assembly macros for

> specific syscalls (such as lseek{64} for x32 witch I think it is not

> avoidable). Also x32 is the only architecture afaik preventing the

> syscall-cancel.h cleanup currently.


There is fine with me as long as the implementation is correct for
x32.   But the current one isn't correct for x32.

Thanks.

-- 
H.J.
diff mbox series

Patch

diff --git a/sysdeps/unix/sysv/linux/x86_64/sysdep.h b/sysdeps/unix/sysv/linux/x86_64/sysdep.h
index 7b8bd79..6d0a6f4 100644
--- a/sysdeps/unix/sysv/linux/x86_64/sysdep.h
+++ b/sysdeps/unix/sysv/linux/x86_64/sysdep.h
@@ -221,33 +221,148 @@ 
 /* Registers clobbered by syscall.  */
 # define REGISTERS_CLOBBERED_BY_SYSCALL "cc", "r11", "cx"
 
-# define INTERNAL_SYSCALL_NCS(name, err, nr, args...) \
-  ({									      \
-    unsigned long int resultvar;					      \
-    LOAD_ARGS_##nr (args)						      \
-    LOAD_REGS_##nr							      \
-    asm volatile (							      \
-    "syscall\n\t"							      \
-    : "=a" (resultvar)							      \
-    : "0" (name) ASM_ARGS_##nr : "memory", REGISTERS_CLOBBERED_BY_SYSCALL);   \
-    (long int) resultvar; })
-# undef INTERNAL_SYSCALL
-# define INTERNAL_SYSCALL(name, err, nr, args...) \
-  INTERNAL_SYSCALL_NCS (__NR_##name, err, nr, ##args)
-
-# define INTERNAL_SYSCALL_NCS_TYPES(name, err, nr, args...) \
-  ({									      \
-    unsigned long int resultvar;					      \
-    LOAD_ARGS_TYPES_##nr (args)						      \
-    LOAD_REGS_TYPES_##nr (args)						      \
-    asm volatile (							      \
-    "syscall\n\t"							      \
-    : "=a" (resultvar)							      \
-    : "0" (name) ASM_ARGS_##nr : "memory", REGISTERS_CLOBBERED_BY_SYSCALL);   \
-    (long int) resultvar; })
-# undef INTERNAL_SYSCALL_TYPES
-# define INTERNAL_SYSCALL_TYPES(name, err, nr, args...) \
-  INTERNAL_SYSCALL_NCS_TYPES (__NR_##name, err, nr, ##args)
+/* Create a variable 'name' based on type 'X' to avoid explicit types.
+   This is mainly used set use 64-bits arguments in x32.   */
+#define TYPEFY(X, name) __typeof__ ((X) - (X)) name
+/* Explicit cast the argument to avoid integer from pointer warning on
+   x32.  */
+#define ARGIFY(X) ((__typeof__ ((X) - (X))) (X))
+
+#undef INTERNAL_SYSCALL
+#define INTERNAL_SYSCALL(name, err, nr, args...)			\
+	internal_syscall##nr (SYS_ify (name), err, args)
+
+#undef INTERNAL_SYSCALL_NCS
+#define INTERNAL_SYSCALL_NCS(number, err, nr, args...)			\
+	internal_syscall##nr (number, err, args)
+
+#undef internal_syscall0
+#define internal_syscall0(number, err, dummy...)			\
+({									\
+    unsigned long int resultvar;					\
+    asm volatile (							\
+    "syscall\n\t"							\
+    : "=a" (resultvar)							\
+    : "0" (number)							\
+    : "memory", REGISTERS_CLOBBERED_BY_SYSCALL);			\
+    (long int) resultvar;						\
+})
+
+#undef internal_syscall1
+#define internal_syscall1(number, err, arg1)				\
+({									\
+    unsigned long int resultvar;					\
+    TYPEFY (arg1, __arg1) = ARGIFY (arg1);			 	\
+    register TYPEFY (arg1, _a1) asm ("rdi") = __arg1;			\
+    asm volatile (							\
+    "syscall\n\t"							\
+    : "=a" (resultvar)							\
+    : "0" (number), "r" (_a1)						\
+    : "memory", REGISTERS_CLOBBERED_BY_SYSCALL);			\
+    (long int) resultvar;						\
+})
+
+#undef internal_syscall2
+#define internal_syscall2(number, err, arg1, arg2)			\
+({									\
+    unsigned long int resultvar;					\
+    TYPEFY (arg2, __arg2) = ARGIFY (arg2);			 	\
+    TYPEFY (arg1, __arg1) = ARGIFY (arg1);			 	\
+    register TYPEFY (arg2, _a2) asm ("rsi") = __arg2;			\
+    register TYPEFY (arg1, _a1) asm ("rdi") = __arg1;			\
+    asm volatile (							\
+    "syscall\n\t"							\
+    : "=a" (resultvar)							\
+    : "0" (number), "r" (_a1), "r" (_a2)				\
+    : "memory", REGISTERS_CLOBBERED_BY_SYSCALL);			\
+    (long int) resultvar;						\
+})
+
+#undef internal_syscall3
+#define internal_syscall3(number, err, arg1, arg2, arg3)		\
+({									\
+    unsigned long int resultvar;					\
+    TYPEFY (arg3, __arg3) = ARGIFY (arg3);			 	\
+    TYPEFY (arg2, __arg2) = ARGIFY (arg2);			 	\
+    TYPEFY (arg1, __arg1) = ARGIFY (arg1);			 	\
+    register TYPEFY (arg3, _a3) asm ("rdx") = __arg3;			\
+    register TYPEFY (arg2, _a2) asm ("rsi") = __arg2;			\
+    register TYPEFY (arg1, _a1) asm ("rdi") = __arg1;			\
+    asm volatile (							\
+    "syscall\n\t"							\
+    : "=a" (resultvar)							\
+    : "0" (number), "r" (_a1), "r" (_a2), "r" (_a3)			\
+    : "memory", REGISTERS_CLOBBERED_BY_SYSCALL);			\
+    (long int) resultvar;						\
+})
+
+#undef internal_syscall4
+#define internal_syscall4(number, err, arg1, arg2, arg3, arg4)		\
+({									\
+    unsigned long int resultvar;					\
+    TYPEFY (arg4, __arg4) = ARGIFY (arg4);			 	\
+    TYPEFY (arg3, __arg3) = ARGIFY (arg3);			 	\
+    TYPEFY (arg2, __arg2) = ARGIFY (arg2);			 	\
+    TYPEFY (arg1, __arg1) = ARGIFY (arg1);			 	\
+    register TYPEFY (arg4, _a4) asm ("r10") = __arg4;			\
+    register TYPEFY (arg3, _a3) asm ("rdx") = __arg3;			\
+    register TYPEFY (arg2, _a2) asm ("rsi") = __arg2;			\
+    register TYPEFY (arg1, _a1) asm ("rdi") = __arg1;			\
+    asm volatile (							\
+    "syscall\n\t"							\
+    : "=a" (resultvar)							\
+    : "0" (number), "r" (_a1), "r" (_a2), "r" (_a3), "r" (_a4)		\
+    : "memory", REGISTERS_CLOBBERED_BY_SYSCALL);			\
+    (long int) resultvar;						\
+})
+
+#undef internal_syscall5
+#define internal_syscall5(number, err, arg1, arg2, arg3, arg4, arg5)	\
+({									\
+    unsigned long int resultvar;					\
+    TYPEFY (arg5, __arg5) = ARGIFY (arg5);			 	\
+    TYPEFY (arg4, __arg4) = ARGIFY (arg4);			 	\
+    TYPEFY (arg3, __arg3) = ARGIFY (arg3);			 	\
+    TYPEFY (arg2, __arg2) = ARGIFY (arg2);			 	\
+    TYPEFY (arg1, __arg1) = ARGIFY (arg1);			 	\
+    register TYPEFY (arg5, _a5) asm ("r8") = __arg5;			\
+    register TYPEFY (arg4, _a4) asm ("r10") = __arg4;			\
+    register TYPEFY (arg3, _a3) asm ("rdx") = __arg3;			\
+    register TYPEFY (arg2, _a2) asm ("rsi") = __arg2;			\
+    register TYPEFY (arg1, _a1) asm ("rdi") = __arg1;			\
+    asm volatile (							\
+    "syscall\n\t"							\
+    : "=a" (resultvar)							\
+    : "0" (number), "r" (_a1), "r" (_a2), "r" (_a3), "r" (_a4),		\
+      "r" (_a5)								\
+    : "memory", REGISTERS_CLOBBERED_BY_SYSCALL);			\
+    (long int) resultvar;						\
+})
+
+#undef internal_syscall6
+#define internal_syscall6(number, err, arg1, arg2, arg3, arg4, arg5, arg6) \
+({									\
+    unsigned long int resultvar;					\
+    TYPEFY (arg6, __arg6) = ARGIFY (arg6);			 	\
+    TYPEFY (arg5, __arg5) = ARGIFY (arg5);			 	\
+    TYPEFY (arg4, __arg4) = ARGIFY (arg4);			 	\
+    TYPEFY (arg3, __arg3) = ARGIFY (arg3);			 	\
+    TYPEFY (arg2, __arg2) = ARGIFY (arg2);			 	\
+    TYPEFY (arg1, __arg1) = ARGIFY (arg1);			 	\
+    register TYPEFY (arg6, _a6) asm ("r9") = __arg6;			\
+    register TYPEFY (arg5, _a5) asm ("r8") = __arg5;			\
+    register TYPEFY (arg4, _a4) asm ("r10") = __arg4;			\
+    register TYPEFY (arg3, _a3) asm ("rdx") = __arg3;			\
+    register TYPEFY (arg2, _a2) asm ("rsi") = __arg2;			\
+    register TYPEFY (arg1, _a1) asm ("rdi") = __arg1;			\
+    asm volatile (							\
+    "syscall\n\t"							\
+    : "=a" (resultvar)							\
+    : "0" (number), "r" (_a1), "r" (_a2), "r" (_a3), "r" (_a4),		\
+      "r" (_a5), "r" (_a6)						\
+    : "memory", REGISTERS_CLOBBERED_BY_SYSCALL);			\
+    (long int) resultvar;						\
+})
 
 # undef INTERNAL_SYSCALL_ERROR_P
 # define INTERNAL_SYSCALL_ERROR_P(val, err) \
@@ -261,88 +376,6 @@ 
 # define HAVE_GETTIMEOFDAY_VSYSCALL     1
 # define HAVE_GETCPU_VSYSCALL		1
 
-# define LOAD_ARGS_0()
-# define LOAD_REGS_0
-# define ASM_ARGS_0
-
-# define LOAD_ARGS_TYPES_1(t1, a1)					   \
-  t1 __arg1 = (t1) (a1);						   \
-  LOAD_ARGS_0 ()
-# define LOAD_REGS_TYPES_1(t1, a1)					   \
-  register t1 _a1 asm ("rdi") = __arg1;					   \
-  LOAD_REGS_0
-# define ASM_ARGS_1	ASM_ARGS_0, "r" (_a1)
-# define LOAD_ARGS_1(a1)						   \
-  LOAD_ARGS_TYPES_1 (long int, a1)
-# define LOAD_REGS_1							   \
-  LOAD_REGS_TYPES_1 (long int, a1)
-
-# define LOAD_ARGS_TYPES_2(t1, a1, t2, a2)				   \
-  t2 __arg2 = (t2) (a2);						   \
-  LOAD_ARGS_TYPES_1 (t1, a1)
-# define LOAD_REGS_TYPES_2(t1, a1, t2, a2)				   \
-  register t2 _a2 asm ("rsi") = __arg2;					   \
-  LOAD_REGS_TYPES_1(t1, a1)
-# define ASM_ARGS_2	ASM_ARGS_1, "r" (_a2)
-# define LOAD_ARGS_2(a1, a2)						   \
-  LOAD_ARGS_TYPES_2 (long int, a1, long int, a2)
-# define LOAD_REGS_2							   \
-  LOAD_REGS_TYPES_2 (long int, a1, long int, a2)
-
-# define LOAD_ARGS_TYPES_3(t1, a1, t2, a2, t3, a3)			   \
-  t3 __arg3 = (t3) (a3);						   \
-  LOAD_ARGS_TYPES_2 (t1, a1, t2, a2)
-# define LOAD_REGS_TYPES_3(t1, a1, t2, a2, t3, a3)			   \
-  register t3 _a3 asm ("rdx") = __arg3;					   \
-  LOAD_REGS_TYPES_2(t1, a1, t2, a2)
-# define ASM_ARGS_3	ASM_ARGS_2, "r" (_a3)
-# define LOAD_ARGS_3(a1, a2, a3)					   \
-  LOAD_ARGS_TYPES_3 (long int, a1, long int, a2, long int, a3)
-# define LOAD_REGS_3							   \
-  LOAD_REGS_TYPES_3 (long int, a1, long int, a2, long int, a3)
-
-# define LOAD_ARGS_TYPES_4(t1, a1, t2, a2, t3, a3, t4, a4)		   \
-  t4 __arg4 = (t4) (a4);						   \
-  LOAD_ARGS_TYPES_3 (t1, a1, t2, a2, t3, a3)
-# define LOAD_REGS_TYPES_4(t1, a1, t2, a2, t3, a3, t4, a4)		   \
-  register t4 _a4 asm ("r10") = __arg4;					   \
-  LOAD_REGS_TYPES_3(t1, a2, t2, a2, t3, a3)
-# define ASM_ARGS_4	ASM_ARGS_3, "r" (_a4)
-# define LOAD_ARGS_4(a1, a2, a3, a4)					   \
-  LOAD_ARGS_TYPES_4 (long int, a1, long int, a2, long int, a3,		   \
-		     long int, a4)
-# define LOAD_REGS_4							   \
-  LOAD_REGS_TYPES_4 (long int, a1, long int, a2, long int, a3,		   \
-		     long int, a4)
-
-# define LOAD_ARGS_TYPES_5(t1, a1, t2, a2, t3, a3, t4, a4, t5, a5)	   \
-  t5 __arg5 = (t5) (a5);						   \
-  LOAD_ARGS_TYPES_4 (t1, a1, t2, a2, t3, a3, t4, a4)
-# define LOAD_REGS_TYPES_5(t1, a1, t2, a2, t3, a3, t4, a4, t5, a5)	   \
-  register t5 _a5 asm ("r8") = __arg5;					   \
-  LOAD_REGS_TYPES_4 (t1, a1, t2, a2, t3, a3, t4, a4)
-# define ASM_ARGS_5	ASM_ARGS_4, "r" (_a5)
-# define LOAD_ARGS_5(a1, a2, a3, a4, a5)				   \
-  LOAD_ARGS_TYPES_5 (long int, a1, long int, a2, long int, a3,		   \
-		     long int, a4, long int, a5)
-# define LOAD_REGS_5							   \
-  LOAD_REGS_TYPES_5 (long int, a1, long int, a2, long int, a3,		   \
-		     long int, a4, long int, a5)
-
-# define LOAD_ARGS_TYPES_6(t1, a1, t2, a2, t3, a3, t4, a4, t5, a5, t6, a6) \
-  t6 __arg6 = (t6) (a6);						   \
-  LOAD_ARGS_TYPES_5 (t1, a1, t2, a2, t3, a3, t4, a4, t5, a5)
-# define LOAD_REGS_TYPES_6(t1, a1, t2, a2, t3, a3, t4, a4, t5, a5, t6, a6) \
-  register t6 _a6 asm ("r9") = __arg6;					   \
-  LOAD_REGS_TYPES_5 (t1, a1, t2, a2, t3, a3, t4, a4, t5, a5)
-# define ASM_ARGS_6	ASM_ARGS_5, "r" (_a6)
-# define LOAD_ARGS_6(a1, a2, a3, a4, a5, a6)				   \
-  LOAD_ARGS_TYPES_6 (long int, a1, long int, a2, long int, a3,		   \
-		     long int, a4, long int, a5, long int, a6)
-# define LOAD_REGS_6							   \
-  LOAD_REGS_TYPES_6 (long int, a1, long int, a2, long int, a3,		   \
-		     long int, a4, long int, a5, long int, a6)
-
 #endif	/* __ASSEMBLER__ */
 
 
diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/times.c b/sysdeps/unix/sysv/linux/x86_64/x32/times.c
index d56106e..8763047 100644
--- a/sysdeps/unix/sysv/linux/x86_64/x32/times.c
+++ b/sysdeps/unix/sysv/linux/x86_64/x32/times.c
@@ -19,17 +19,19 @@ 
 #include <sysdep.h>
 
 /* Linux times system call returns 64-bit integer.  */
-#undef INTERNAL_SYSCALL_NCS
-#define INTERNAL_SYSCALL_NCS(name, err, nr, args...) \
-  ({									      \
-    unsigned long long int resultvar;					      \
-    LOAD_ARGS_##nr (args)						      \
-    LOAD_REGS_##nr							      \
-    asm volatile (							      \
-    "syscall\n\t"							      \
-    : "=a" (resultvar)							      \
-    : "0" (name) ASM_ARGS_##nr : "memory", REGISTERS_CLOBBERED_BY_SYSCALL);   \
-    (long long int) resultvar; })
+#undef internal_syscall1
+#define internal_syscall1(number, err, arg1)				\
+({									\
+    unsigned long long int resultvar;					\
+    TYPEFY (arg1, __arg1) = ARGIFY (arg1);			 	\
+    register TYPEFY (arg1, _a1) asm ("rdi") = __arg1;			\
+    asm volatile (							\
+    "syscall\n\t"							\
+    : "=a" (resultvar)							\
+    : "0" (number), "r" (_a1)						\
+    : "memory", REGISTERS_CLOBBERED_BY_SYSCALL);			\
+    (long long int) resultvar;						\
+})
 
 #undef INTERNAL_SYSCALL_ERROR_P
 #define INTERNAL_SYSCALL_ERROR_P(val, err) \