David Woodhouse via llvm-dev
2018-Feb-09 16:18 UTC
[llvm-dev] [RFC HACK] Make clang hate percpu.h less in 32-bit mode
Neither clang nor GCC like this very much with -m32: long long ret; asm ("movb $5, %0" : "=q" (ret)); However, GCC can tolerate this variant: long long ret; switch (sizeof(ret)) { case 1: asm ("movb $5, %0" : "=q" (ret)); case 8: ; } Clang, on the other hand, won't accept that because it validates the inline asm for the '1' case *before* the optimisation phase where it realises that it wouldn't have to emit it anyway. This patch puts some casts in to make clang less unhappy. I don't like it very much. Note that we don't have the same problem for the "=r" case, where a 64-bit value *also* doesn't fit. This is because even if it *does* have to emit it, clang will happily and silently do so even though it's clearly bogus: long long ret; asm ("movl $5, %0" : "=r" (ret)); $ clang -c -o q.o q.c -m32 $ gcc -c -o q.o q.c -m32 q.c: In function ‘foo’: q.c:6:1: warning: unsupported size for integer register --- arch/x86/include/asm/percpu.h | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/arch/x86/include/asm/percpu.h b/arch/x86/include/asm/percpu.h index ba3c523aaf16..3b0e413670e4 100644 --- a/arch/x86/include/asm/percpu.h +++ b/arch/x86/include/asm/percpu.h @@ -99,7 +99,7 @@ do { \ case 1: \ asm(op "b %1,"__percpu_arg(0) \ : "+m" (var) \ - : "qi" ((pto_T__)(val))); \ + : "qi" ((unsigned char)(unsigned long)(val))); \ break; \ case 2: \ asm(op "w %1,"__percpu_arg(0) \ @@ -144,7 +144,7 @@ do { \ else \ asm("addb %1, "__percpu_arg(0) \ : "+m" (var) \ - : "qi" ((pao_T__)(val))); \ + : "qi" ((unsigned char)(unsigned long)(val))); \ break; \ case 2: \ if (pao_ID__ == 1) \ @@ -182,12 +182,14 @@ do { \ #define percpu_from_op(op, var) \ ({ \ + unsigned char pfo_u8__; \ typeof(var) pfo_ret__; \ switch (sizeof(var)) { \ case 1: \ asm(op "b "__percpu_arg(1)",%0" \ - : "=q" (pfo_ret__) \ + : "=q" (pfo_u8__) \ : "m" (var)); \ + pfo_ret__ = (typeof(var))(unsigned long)pfo_u8__; \ break; \ case 2: \ asm(op "w "__percpu_arg(1)",%0" \ @@ -211,12 +213,14 @@ do { \ #define percpu_stable_op(op, var) \ ({ \ + unsigned char pfo_u8__; \ typeof(var) pfo_ret__; \ switch (sizeof(var)) { \ case 1: \ asm(op "b "__percpu_arg(P1)",%0" \ - : "=q" (pfo_ret__) \ + : "=q" (pfo_u8__) \ : "p" (&(var))); \ + pfo_ret__ = (typeof(var))(unsigned long)pfo_u8__; \ break; \ case 2: \ asm(op "w "__percpu_arg(P1)",%0" \ -- 2.14.3