Commit 0697fbd3 authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] const vs. __attribute__((const)) confusion

From: "H. Peter Anvin" <hpa@zytor.com>

Declaring a function to return a const scalar value is pretty meaningless. 
These functions are really trying to say that they don't alter any external
state.

Fix that up by using __attribute__((const)), if the compiler supports that.
parent 477702e9
...@@ -2,20 +2,21 @@ ...@@ -2,20 +2,21 @@
#define _CRIS_ARCH_BYTEORDER_H #define _CRIS_ARCH_BYTEORDER_H
#include <asm/types.h> #include <asm/types.h>
#include <linux/compiler.h>
/* we just define these two (as we can do the swap in a single /* we just define these two (as we can do the swap in a single
* asm instruction in CRIS) and the arch-independent files will put * asm instruction in CRIS) and the arch-independent files will put
* them together into ntohl etc. * them together into ntohl etc.
*/ */
extern __inline__ __const__ __u32 ___arch__swab32(__u32 x) extern __inline__ __attribute_const__ __u32 ___arch__swab32(__u32 x)
{ {
__asm__ ("swapwb %0" : "=r" (x) : "0" (x)); __asm__ ("swapwb %0" : "=r" (x) : "0" (x));
return(x); return(x);
} }
extern __inline__ __const__ __u16 ___arch__swab16(__u16 x) extern __inline__ __attribute_const__ __u16 ___arch__swab16(__u16 x)
{ {
__asm__ ("swapb %0" : "=r" (x) : "0" (x)); __asm__ ("swapb %0" : "=r" (x) : "0" (x));
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
#define _I386_BYTEORDER_H #define _I386_BYTEORDER_H
#include <asm/types.h> #include <asm/types.h>
#include <linux/compiler.h>
#ifdef __GNUC__ #ifdef __GNUC__
...@@ -10,7 +11,7 @@ ...@@ -10,7 +11,7 @@
#include <linux/config.h> #include <linux/config.h>
#endif #endif
static __inline__ __const__ __u32 ___arch__swab32(__u32 x) static __inline__ __attribute_const__ __u32 ___arch__swab32(__u32 x)
{ {
#ifdef CONFIG_X86_BSWAP #ifdef CONFIG_X86_BSWAP
__asm__("bswap %0" : "=r" (x) : "0" (x)); __asm__("bswap %0" : "=r" (x) : "0" (x));
...@@ -24,18 +25,7 @@ static __inline__ __const__ __u32 ___arch__swab32(__u32 x) ...@@ -24,18 +25,7 @@ static __inline__ __const__ __u32 ___arch__swab32(__u32 x)
return x; return x;
} }
/* gcc should generate this for open coded C now too. May be worth switching to static __inline__ __attribute_const__ __u64 ___arch__swab64(__u64 val)
it because inline assembly cannot be scheduled. -AK */
static __inline__ __const__ __u16 ___arch__swab16(__u16 x)
{
__asm__("xchgb %b0,%h0" /* swap bytes */
: "=q" (x)
: "0" (x));
return x;
}
static inline __u64 ___arch__swab64(__u64 val)
{ {
union { union {
struct { __u32 a,b; } s; struct { __u32 a,b; } s;
...@@ -54,9 +44,11 @@ static inline __u64 ___arch__swab64(__u64 val) ...@@ -54,9 +44,11 @@ static inline __u64 ___arch__swab64(__u64 val)
return v.u; return v.u;
} }
/* Do not define swab16. Gcc is smart enough to recognize "C" version and
convert it into rotation or exhange. */
#define __arch__swab64(x) ___arch__swab64(x) #define __arch__swab64(x) ___arch__swab64(x)
#define __arch__swab32(x) ___arch__swab32(x) #define __arch__swab32(x) ___arch__swab32(x)
#define __arch__swab16(x) ___arch__swab16(x)
#define __BYTEORDER_HAS_U64__ #define __BYTEORDER_HAS_U64__
......
...@@ -8,8 +8,9 @@ ...@@ -8,8 +8,9 @@
#include <asm/types.h> #include <asm/types.h>
#include <asm/intrinsics.h> #include <asm/intrinsics.h>
#include <linux/compiler.h>
static __inline__ __const__ __u64 static __inline__ __attribute_const__ __u64
__ia64_swab64 (__u64 x) __ia64_swab64 (__u64 x)
{ {
__u64 result; __u64 result;
...@@ -18,13 +19,13 @@ __ia64_swab64 (__u64 x) ...@@ -18,13 +19,13 @@ __ia64_swab64 (__u64 x)
return result; return result;
} }
static __inline__ __const__ __u32 static __inline__ __attribute_const__ __u32
__ia64_swab32 (__u32 x) __ia64_swab32 (__u32 x)
{ {
return __ia64_swab64(x) >> 32; return __ia64_swab64(x) >> 32;
} }
static __inline__ __const__ __u16 static __inline__ __attribute_const__ __u16
__ia64_swab16(__u16 x) __ia64_swab16(__u16 x)
{ {
return __ia64_swab64(x) >> 48; return __ia64_swab64(x) >> 48;
......
...@@ -2,10 +2,11 @@ ...@@ -2,10 +2,11 @@
#define _M68K_BYTEORDER_H #define _M68K_BYTEORDER_H
#include <asm/types.h> #include <asm/types.h>
#include <linux/compiler.h>
#ifdef __GNUC__ #ifdef __GNUC__
static __inline__ __const__ __u32 ___arch__swab32(__u32 val) static __inline__ __attribute_const__ __u32 ___arch__swab32(__u32 val)
{ {
__asm__("rolw #8,%0; swap %0; rolw #8,%0" : "=d" (val) : "0" (val)); __asm__("rolw #8,%0; swap %0; rolw #8,%0" : "=d" (val) : "0" (val));
return val; return val;
......
...@@ -2,10 +2,11 @@ ...@@ -2,10 +2,11 @@
#define _PARISC_BYTEORDER_H #define _PARISC_BYTEORDER_H
#include <asm/types.h> #include <asm/types.h>
#include <linux/compiler.h>
#ifdef __GNUC__ #ifdef __GNUC__
static __inline__ __const__ __u16 ___arch__swab16(__u16 x) static __inline__ __attribute_const__ __u16 ___arch__swab16(__u16 x)
{ {
__asm__("dep %0, 15, 8, %0\n\t" /* deposit 00ab -> 0bab */ __asm__("dep %0, 15, 8, %0\n\t" /* deposit 00ab -> 0bab */
"shd %%r0, %0, 8, %0" /* shift 000000ab -> 00ba */ "shd %%r0, %0, 8, %0" /* shift 000000ab -> 00ba */
...@@ -14,7 +15,7 @@ static __inline__ __const__ __u16 ___arch__swab16(__u16 x) ...@@ -14,7 +15,7 @@ static __inline__ __const__ __u16 ___arch__swab16(__u16 x)
return x; return x;
} }
static __inline__ __const__ __u32 ___arch__swab24(__u32 x) static __inline__ __attribute_const__ __u32 ___arch__swab24(__u32 x)
{ {
__asm__("shd %0, %0, 8, %0\n\t" /* shift xabcxabc -> cxab */ __asm__("shd %0, %0, 8, %0\n\t" /* shift xabcxabc -> cxab */
"dep %0, 15, 8, %0\n\t" /* deposit cxab -> cbab */ "dep %0, 15, 8, %0\n\t" /* deposit cxab -> cbab */
...@@ -24,7 +25,7 @@ static __inline__ __const__ __u32 ___arch__swab24(__u32 x) ...@@ -24,7 +25,7 @@ static __inline__ __const__ __u32 ___arch__swab24(__u32 x)
return x; return x;
} }
static __inline__ __const__ __u32 ___arch__swab32(__u32 x) static __inline__ __attribute_const__ __u32 ___arch__swab32(__u32 x)
{ {
unsigned int temp; unsigned int temp;
__asm__("shd %0, %0, 16, %1\n\t" /* shift abcdabcd -> cdab */ __asm__("shd %0, %0, 16, %1\n\t" /* shift abcdabcd -> cdab */
...@@ -47,7 +48,7 @@ static __inline__ __const__ __u32 ___arch__swab32(__u32 x) ...@@ -47,7 +48,7 @@ static __inline__ __const__ __u32 ___arch__swab32(__u32 x)
** HSHR 67452301 -> *6*4*2*0 into %0 ** HSHR 67452301 -> *6*4*2*0 into %0
** OR %0 | %1 -> 76543210 into %0 (all done!) ** OR %0 | %1 -> 76543210 into %0 (all done!)
*/ */
static __inline__ __const__ __u64 ___arch__swab64(__u64 x) { static __inline__ __attribute_const__ __u64 ___arch__swab64(__u64 x) {
__u64 temp; __u64 temp;
__asm__("permh,3210 %0, %0\n\t" __asm__("permh,3210 %0, %0\n\t"
"hshl %0, 8, %1\n\t" "hshl %0, 8, %1\n\t"
...@@ -60,7 +61,7 @@ static __inline__ __const__ __u64 ___arch__swab64(__u64 x) { ...@@ -60,7 +61,7 @@ static __inline__ __const__ __u64 ___arch__swab64(__u64 x) {
#define __arch__swab64(x) ___arch__swab64(x) #define __arch__swab64(x) ___arch__swab64(x)
#define __BYTEORDER_HAS_U64__ #define __BYTEORDER_HAS_U64__
#elif !defined(__STRICT_ANSI__) #elif !defined(__STRICT_ANSI__)
static __inline__ __const__ __u64 ___arch__swab64(__u64 x) static __inline__ __attribute_const__ __u64 ___arch__swab64(__u64 x)
{ {
__u32 t1 = ___arch__swab32((__u32) x); __u32 t1 = ___arch__swab32((__u32) x);
__u32 t2 = ___arch__swab32((__u32) (x >> 32)); __u32 t2 = ___arch__swab32((__u32) (x >> 32));
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
#define _PPC_BYTEORDER_H #define _PPC_BYTEORDER_H
#include <asm/types.h> #include <asm/types.h>
#include <linux/compiler.h>
#ifdef __GNUC__ #ifdef __GNUC__
#ifdef __KERNEL__ #ifdef __KERNEL__
...@@ -32,7 +33,7 @@ extern __inline__ void st_le32(volatile unsigned *addr, const unsigned val) ...@@ -32,7 +33,7 @@ extern __inline__ void st_le32(volatile unsigned *addr, const unsigned val)
__asm__ __volatile__ ("stwbrx %1,0,%2" : "=m" (*addr) : "r" (val), "r" (addr)); __asm__ __volatile__ ("stwbrx %1,0,%2" : "=m" (*addr) : "r" (val), "r" (addr));
} }
static __inline__ __const__ __u16 ___arch__swab16(__u16 value) static __inline__ __attribute_const__ __u16 ___arch__swab16(__u16 value)
{ {
__u16 result; __u16 result;
...@@ -40,7 +41,7 @@ static __inline__ __const__ __u16 ___arch__swab16(__u16 value) ...@@ -40,7 +41,7 @@ static __inline__ __const__ __u16 ___arch__swab16(__u16 value)
return result; return result;
} }
static __inline__ __const__ __u32 ___arch__swab32(__u32 value) static __inline__ __attribute_const__ __u32 ___arch__swab32(__u32 value)
{ {
__u32 result; __u32 result;
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
*/ */
#include <asm/types.h> #include <asm/types.h>
#include <linux/compiler.h>
#ifdef __GNUC__ #ifdef __GNUC__
#ifdef __KERNEL__ #ifdef __KERNEL__
...@@ -40,7 +41,7 @@ static __inline__ void st_le32(volatile __u32 *addr, const __u32 val) ...@@ -40,7 +41,7 @@ static __inline__ void st_le32(volatile __u32 *addr, const __u32 val)
} }
#if 0 #if 0
static __inline__ __const__ __u16 ___arch__swab16(__u16 value) static __inline__ __attribute_const__ __u16 ___arch__swab16(__u16 value)
{ {
__u16 result; __u16 result;
...@@ -50,7 +51,7 @@ static __inline__ __const__ __u16 ___arch__swab16(__u16 value) ...@@ -50,7 +51,7 @@ static __inline__ __const__ __u16 ___arch__swab16(__u16 value)
return result; return result;
} }
static __inline__ __const__ __u32 ___arch__swab32(__u32 value) static __inline__ __attribute_const__ __u32 ___arch__swab32(__u32 value)
{ {
__u32 result; __u32 result;
...@@ -62,7 +63,7 @@ static __inline__ __const__ __u32 ___arch__swab32(__u32 value) ...@@ -62,7 +63,7 @@ static __inline__ __const__ __u32 ___arch__swab32(__u32 value)
return result; return result;
} }
static __inline__ __const__ __u64 ___arch__swab64(__u64 value) static __inline__ __attribute_const__ __u64 ___arch__swab64(__u64 value)
{ {
__u64 result; __u64 result;
#error implement me #error implement me
......
...@@ -6,8 +6,9 @@ ...@@ -6,8 +6,9 @@
*/ */
#include <asm/types.h> #include <asm/types.h>
#include <linux/compiler.h>
static __inline__ __const__ __u32 ___arch__swab32(__u32 x) static __inline__ __attribute_const__ __u32 ___arch__swab32(__u32 x)
{ {
__asm__("swap.b %0, %0\n\t" __asm__("swap.b %0, %0\n\t"
"swap.w %0, %0\n\t" "swap.w %0, %0\n\t"
...@@ -17,7 +18,7 @@ static __inline__ __const__ __u32 ___arch__swab32(__u32 x) ...@@ -17,7 +18,7 @@ static __inline__ __const__ __u32 ___arch__swab32(__u32 x)
return x; return x;
} }
static __inline__ __const__ __u16 ___arch__swab16(__u16 x) static __inline__ __attribute_const__ __u16 ___arch__swab16(__u16 x)
{ {
__asm__("swap.b %0, %0" __asm__("swap.b %0, %0"
: "=r" (x) : "=r" (x)
......
...@@ -15,17 +15,18 @@ ...@@ -15,17 +15,18 @@
#define __V850_BYTEORDER_H__ #define __V850_BYTEORDER_H__
#include <asm/types.h> #include <asm/types.h>
#include <linux/compiler.h>
#ifdef __GNUC__ #ifdef __GNUC__
static __inline__ __const__ __u32 ___arch__swab32 (__u32 word) static __inline__ __attribute_const__ __u32 ___arch__swab32 (__u32 word)
{ {
__u32 res; __u32 res;
__asm__ ("bsw %1, %0" : "=r" (res) : "r" (word)); __asm__ ("bsw %1, %0" : "=r" (res) : "r" (word));
return res; return res;
} }
static __inline__ __const__ __u16 ___arch__swab16 (__u16 half_word) static __inline__ __attribute_const__ __u16 ___arch__swab16 (__u16 half_word)
{ {
__u16 res; __u16 res;
__asm__ ("bsh %1, %0" : "=r" (res) : "r" (half_word)); __asm__ ("bsh %1, %0" : "=r" (res) : "r" (half_word));
......
...@@ -2,16 +2,17 @@ ...@@ -2,16 +2,17 @@
#define _X86_64_BYTEORDER_H #define _X86_64_BYTEORDER_H
#include <asm/types.h> #include <asm/types.h>
#include <linux/compiler.h>
#ifdef __GNUC__ #ifdef __GNUC__
static __inline__ __const__ __u64 ___arch__swab64(__u64 x) static __inline__ __attribute_const__ __u64 ___arch__swab64(__u64 x)
{ {
__asm__("bswapq %0" : "=r" (x) : "0" (x)); __asm__("bswapq %0" : "=r" (x) : "0" (x));
return x; return x;
} }
static __inline__ __const__ __u32 ___arch__swab32(__u32 x) static __inline__ __attribute_const__ __u32 ___arch__swab32(__u32 x)
{ {
__asm__("bswapl %0" : "=r" (x) : "0" (x)); __asm__("bswapl %0" : "=r" (x) : "0" (x));
return x; return x;
......
...@@ -15,6 +15,8 @@ ...@@ -15,6 +15,8 @@
* *
*/ */
#include <linux/compiler.h>
/* casts are necessary for constants, because we never know how for sure /* casts are necessary for constants, because we never know how for sure
* how U/UL/ULL map to __u16, __u32, __u64. At least not in a portable way. * how U/UL/ULL map to __u16, __u32, __u64. At least not in a portable way.
*/ */
...@@ -128,7 +130,7 @@ ...@@ -128,7 +130,7 @@
#endif /* OPTIMIZE */ #endif /* OPTIMIZE */
static __inline__ __const__ __u16 __fswab16(__u16 x) static __inline__ __attribute_const__ __u16 __fswab16(__u16 x)
{ {
return __arch__swab16(x); return __arch__swab16(x);
} }
...@@ -141,7 +143,7 @@ static __inline__ void __swab16s(__u16 *addr) ...@@ -141,7 +143,7 @@ static __inline__ void __swab16s(__u16 *addr)
__arch__swab16s(addr); __arch__swab16s(addr);
} }
static __inline__ __const__ __u32 __fswab32(__u32 x) static __inline__ __attribute_const__ __u32 __fswab32(__u32 x)
{ {
return __arch__swab32(x); return __arch__swab32(x);
} }
...@@ -155,7 +157,7 @@ static __inline__ void __swab32s(__u32 *addr) ...@@ -155,7 +157,7 @@ static __inline__ void __swab32s(__u32 *addr)
} }
#ifdef __BYTEORDER_HAS_U64__ #ifdef __BYTEORDER_HAS_U64__
static __inline__ __const__ __u64 __fswab64(__u64 x) static __inline__ __attribute_const__ __u64 __fswab64(__u64 x)
{ {
# ifdef __SWAB_64_THRU_32__ # ifdef __SWAB_64_THRU_32__
__u32 h = x >> 32; __u32 h = x >> 32;
......
...@@ -12,3 +12,4 @@ ...@@ -12,3 +12,4 @@
#define __deprecated __attribute__((deprecated)) #define __deprecated __attribute__((deprecated))
#define __attribute_used__ __attribute__((__used__)) #define __attribute_used__ __attribute__((__used__))
#define __attribute_pure__ __attribute__((pure)) #define __attribute_pure__ __attribute__((pure))
#define __attribute_const__ __attribute__((__const__))
...@@ -20,4 +20,5 @@ ...@@ -20,4 +20,5 @@
*/ */
#if __GNUC_MINOR__ >= 96 #if __GNUC_MINOR__ >= 96
# define __attribute_pure__ __attribute__((pure)) # define __attribute_pure__ __attribute__((pure))
# define __attribute_const__ __attribute__((__const__))
#endif #endif
...@@ -20,3 +20,4 @@ ...@@ -20,3 +20,4 @@
#endif #endif
#define __attribute_pure__ __attribute__((pure)) #define __attribute_pure__ __attribute__((pure))
#define __attribute_const__ __attribute__((__const__))
...@@ -76,6 +76,24 @@ ...@@ -76,6 +76,24 @@
# define __attribute_pure__ /* unimplemented */ # define __attribute_pure__ /* unimplemented */
#endif #endif
/*
* From the GCC manual:
*
* Many functions do not examine any values except their arguments,
* and have no effects except the return value. Basically this is
* just slightly more strict class than the `pure' attribute above,
* since function is not allowed to read global memory.
*
* Note that a function that has pointer arguments and examines the
* data pointed to must _not_ be declared `const'. Likewise, a
* function that calls a non-`const' function usually must not be
* `const'. It does not make sense for a `const' function to return
* `void'.
*/
#ifndef __attribute_const__
# define __attribute_const__ /* unimplemented */
#endif
/* Optimization barrier */ /* Optimization barrier */
#ifndef barrier #ifndef barrier
# define barrier() __memory_barrier() # define barrier() __memory_barrier()
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment