ip2net: i hate strict aliasing

This commit is contained in:
bol-van 2022-06-13 17:51:07 +03:00
parent 1fcee44443
commit 3842cbbca5
10 changed files with 26 additions and 1 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -102,7 +102,14 @@ static inline const struct in6_addr *mask_from_bitcount6(uint32_t zct)
}
// result = a & b
/*
// this is "correct" solution for strict aliasing feature
// but I don't like this style of coding
// write what I don't mean to force smart optimizer to do what it's best
// it produces better code sometimes but not on all compilers/versions/archs
// sometimes it even generates real memcpy calls (mips32,arm32)
// so I will not do it
static void ip6_and(const struct in6_addr *a, const struct in6_addr *b, struct in6_addr *result)
{
uint64_t a_addr[2], b_addr[2];
@ -112,6 +119,24 @@ static void ip6_and(const struct in6_addr *a, const struct in6_addr *b, struct i
a_addr[1] &= b_addr[1];
memcpy(result->s6_addr, a_addr, 16);
}
*/
// YES, from my point of view C should work as a portable assembler. It must do what I instruct it to do.
// that's why I disable strict aliasing for this function. I observed gcc can miscompile with O2/O3 setting if inlined and not coded "correct"
// result = a & b
#if defined(__GNUC__) && !defined(__llvm__)
__attribute__((optimize ("no-strict-aliasing")))
#endif
static void ip6_and(const struct in6_addr *a, const struct in6_addr *b, struct in6_addr *result)
{
#ifdef __SIZEOF_INT128__
// gcc and clang have 128 bit int types on some 64-bit archs. take some advantage
*((unsigned __int128*)result->s6_addr) = *((unsigned __int128*)a->s6_addr) & *((unsigned __int128*)b->s6_addr);
#else
((uint64_t*)result->s6_addr)[0] = ((uint64_t*)a->s6_addr)[0] & ((uint64_t*)b->s6_addr)[0];
((uint64_t*)result->s6_addr)[1] = ((uint64_t*)a->s6_addr)[1] & ((uint64_t*)b->s6_addr)[1];
#endif
}
static void rtrim(char *s)
{