diff -r 000000000000 -r 6474c204b198 mfbt/Alignment.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mfbt/Alignment.h Wed Dec 31 06:09:35 2014 +0100 @@ -0,0 +1,137 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* Functionality related to memory alignment. */ + +#ifndef mozilla_Alignment_h +#define mozilla_Alignment_h + +#include +#include + +namespace mozilla { + +/* + * This class, and the corresponding macro MOZ_ALIGNOF, figures out how many + * bytes of alignment a given type needs. + */ +template +class AlignmentFinder +{ + struct Aligner + { + char c; + T t; + }; + + public: + static const size_t alignment = sizeof(Aligner) - sizeof(T); +}; + +#define MOZ_ALIGNOF(T) mozilla::AlignmentFinder::alignment + +/* + * Declare the MOZ_ALIGNED_DECL macro for declaring aligned types. + * + * For instance, + * + * MOZ_ALIGNED_DECL(char arr[2], 8); + * + * will declare a two-character array |arr| aligned to 8 bytes. + */ + +#if defined(__GNUC__) +# define MOZ_ALIGNED_DECL(_type, _align) \ + _type __attribute__((aligned(_align))) +#elif defined(_MSC_VER) +# define MOZ_ALIGNED_DECL(_type, _align) \ + __declspec(align(_align)) _type +#else +# warning "We don't know how to align variables on this compiler." +# define MOZ_ALIGNED_DECL(_type, _align) _type +#endif + +/* + * AlignedElem is a structure whose alignment is guaranteed to be at least N + * bytes. + * + * We support 1, 2, 4, 8, and 16-bit alignment. + */ +template +struct AlignedElem; + +/* + * We have to specialize this template because GCC doesn't like __attribute__((aligned(foo))) where + * foo is a template parameter. + */ + +template<> +struct AlignedElem<1> +{ + MOZ_ALIGNED_DECL(uint8_t elem, 1); +}; + +template<> +struct AlignedElem<2> +{ + MOZ_ALIGNED_DECL(uint8_t elem, 2); +}; + +template<> +struct AlignedElem<4> +{ + MOZ_ALIGNED_DECL(uint8_t elem, 4); +}; + +template<> +struct AlignedElem<8> +{ + MOZ_ALIGNED_DECL(uint8_t elem, 8); +}; + +template<> +struct AlignedElem<16> +{ + MOZ_ALIGNED_DECL(uint8_t elem, 16); +}; + +/* + * This utility pales in comparison to Boost's aligned_storage. The utility + * simply assumes that uint64_t is enough alignment for anyone. This may need + * to be extended one day... + * + * As an important side effect, pulling the storage into this template is + * enough obfuscation to confuse gcc's strict-aliasing analysis into not giving + * false negatives when we cast from the char buffer to whatever type we've + * constructed using the bytes. + */ +template +struct AlignedStorage +{ + union U { + char bytes[Nbytes]; + uint64_t _; + } u; + + const void* addr() const { return u.bytes; } + void* addr() { return u.bytes; } +}; + +template +struct AlignedStorage2 +{ + union U { + char bytes[sizeof(T)]; + uint64_t _; + } u; + + const T* addr() const { return reinterpret_cast(u.bytes); } + T* addr() { return static_cast(static_cast(u.bytes)); } +}; + +} /* namespace mozilla */ + +#endif /* mozilla_Alignment_h */