From 79461d20a8d5b7aba6cae5f6fa0fad5e8ac49235 Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Wed, 8 Oct 2014 22:13:31 -0700 Subject: [PATCH] unaligned: Make get_unaligned_be64() compatible on GCC and non-GCC. Until now, with GCC, get_unaligned_be64() had an interface that accepted a "ovs_be64 *", and with other compilers its accepted any pointer-to-64-bit type, but not void *. This commit fixes the problem, making the interface the same in both cases. This fixes a build error on MSVC: lib/nx-match.c(320) : error C2100: illegal indirection lib/nx-match.c(320) : error C2034: 'build_assert_failed' : type of bit field too small for number of bits lib/nx-match.c(320) : error C2296: '%' : illegal, left operand has type 'void *' lib/nx-match.c(320) : error C2198: 'ntohll' : too few arguments for call It might appear that this patch changes get_unaligned_u64() but in fact it onloy moves it earlier in the file (since it is now called from the non-GCC fork of the #if). Reported-by: Alin Serdean Tested-by: Alin Gabriel Serdean Acked-by: Alin Gabriel Serdean Signed-off-by: Ben Pfaff --- lib/unaligned.h | 58 +++++++++++++++++++++++++++++-------------------- 1 file changed, 35 insertions(+), 23 deletions(-) diff --git a/lib/unaligned.h b/lib/unaligned.h index 154eb1338..d56f22b2b 100644 --- a/lib/unaligned.h +++ b/lib/unaligned.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2011 Nicira, Inc. + * Copyright (c) 2010, 2011, 2014 Nicira, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -37,6 +37,27 @@ static inline void put_unaligned_be16(ovs_be16 *, ovs_be16); static inline void put_unaligned_be32(ovs_be32 *, ovs_be32); static inline void put_unaligned_be64(ovs_be64 *, ovs_be64); +/* uint64_t get_unaligned_u64(uint64_t *p); + * + * Returns the value of the possibly misaligned uint64_t at 'p'. 'p' may + * actually be any type that points to a 64-bit integer. That is, on Unix-like + * 32-bit ABIs, it may point to an "unsigned long long int", and on Unix-like + * 64-bit ABIs, it may point to an "unsigned long int" or an "unsigned long + * long int". + * + * This is special-cased because on some Linux targets, the kernel __u64 is + * unsigned long long int and the userspace uint64_t is unsigned long int, so + * that any single function prototype would fail to accept one or the other. + * + * Below, "sizeof (*(P) % 1)" verifies that *P has an integer type, since + * operands to % must be integers. + */ +#define get_unaligned_u64(P) \ + (BUILD_ASSERT(sizeof *(P) == 8), \ + BUILD_ASSERT_GCCONLY(!TYPE_IS_SIGNED(typeof(*(P)))), \ + (void) sizeof (*(P) % 1), \ + get_unaligned_u64__((const uint64_t *) (P))) + #ifdef __GNUC__ /* GCC implementations. */ #define GCC_UNALIGNED_ACCESSORS(TYPE, ABBREV) \ @@ -136,32 +157,23 @@ static inline void put_unaligned_u64__(uint64_t *p_, uint64_t x_) * accessors. */ #define get_unaligned_be16 get_unaligned_u16 #define get_unaligned_be32 get_unaligned_u32 -#define get_unaligned_be64 get_unaligned_u64 #define put_unaligned_be16 put_unaligned_u16 #define put_unaligned_be32 put_unaligned_u32 #define put_unaligned_be64 put_unaligned_u64 -#endif -/* uint64_t get_unaligned_u64(uint64_t *p); - * - * Returns the value of the possibly misaligned uint64_t at 'p'. 'p' may - * actually be any type that points to a 64-bit integer. That is, on Unix-like - * 32-bit ABIs, it may point to an "unsigned long long int", and on Unix-like - * 64-bit ABIs, it may point to an "unsigned long int" or an "unsigned long - * long int". - * - * This is special-cased because on some Linux targets, the kernel __u64 is - * unsigned long long int and the userspace uint64_t is unsigned long int, so - * that any single function prototype would fail to accept one or the other. - * - * Below, "sizeof (*(P) % 1)" verifies that *P has an integer type, since - * operands to % must be integers. - */ -#define get_unaligned_u64(P) \ - (BUILD_ASSERT(sizeof *(P) == 8), \ - BUILD_ASSERT_GCCONLY(!TYPE_IS_SIGNED(typeof(*(P)))), \ - (void) sizeof (*(P) % 1), \ - get_unaligned_u64__((const uint64_t *) (P))) +/* We do not #define get_unaligned_be64 as for the other be functions above, + * because such a definition would mean that get_unaligned_be64() would have a + * different interface in each branch of the #if: with GCC it would take a + * "ovs_be64 *", with other compilers any pointer-to-64-bit-type (but not void + * *). The latter means code like "get_unaligned_be64(ofpbuf_data(b))" would + * work with GCC but not with other compilers, which is surprising and + * undesirable. Hence this wrapper function. */ +static inline ovs_be64 +get_unaligned_be64(const ovs_be64 *p) +{ + return get_unaligned_u64(p); +} +#endif /* Stores 'x' at possibly misaligned address 'p'. * -- 2.20.1