Open64 (mfef90, whirl2f, and IR tools)  TAG: version-openad; SVN changeset: 916
alignof_replacement.h
Go to the documentation of this file.
00001 /* $Id: alignof_replacement.h,v 1.1 2003-12-09 19:10:25 eraxxon Exp $ */
00002 /* -*-Mode: C;-*- */
00003 
00004 /****************************************************************************
00005  * alignof library
00006  *
00007  * Copyright (C) 2003 Martin Buchholz
00008  *
00009  * Permission to copy, use, sell and distribute this software is granted
00010  * provided this copyright notice appears in all copies.
00011  * Permission to modify the code and to distribute modified code is granted
00012  * provided this copyright notice appears in all copies, and a notice
00013  * that the code was modified is included with the copyright notice.
00014  *
00015  * This software is provided "as is" without express or implied warranty,
00016  * and with no claim as to its suitability for any purpose.
00017  *
00018  *
00019  * ----------------------------------------------------------------
00020  * This code is known to work with the following compilers:
00021  * Linux x86 g++ 2.95
00022  * Linux x86 g++ 3.2.1
00023  * Linux x86 g++ 3.3 20030122 pre-release
00024  * Linux x86 g++ 3.4 20030122 pre-release
00025  * Linux x86 Intel compiler Version 7.0
00026  * Windows x86 MS Visual C++ .NET Version 13.00
00027  *
00028  * To work with MS Visual C++, we avoid partial template specialization.
00029  * ----------------------------------------------------------------
00030  *
00031  * See: http://m17n.org/martin/writings/alignof.html
00032  *
00033  ****************************************************************************/
00034 
00035 /****************************************************************************
00036  *
00037  *
00038  * Nathan Tallent: 
00039  *  - Brought into Open64 and made minor cosmetic changes.
00040  *  - Converted initial comments into classic C comments (for non C99
00041  *    compilers).
00042  *
00043  * Description: 
00044  *
00045  * This file provides a relatively portable C and C++ workaround for
00046  * the common compiler builtin alignof().  Note that because the C and
00047  * C++ versions are implemented quite differently, be careful about
00048  * assuming they will produce identical results.
00049  * 
00050  *   ALIGNOF (type)
00051  *   Return alignment of TYPE.
00052  *
00053  *   ALIGNOF_POD_TYPE (type)
00054  *   Return a POD (Plain Ol' Data) type with the same alignment as TYPE.
00055  * 
00056  ****************************************************************************/
00057 
00058 
00059 #ifndef ALIGNOF_REPLACEMENT_HPP_INCLUDED_
00060 #define ALIGNOF_REPLACEMENT_HPP_INCLUDED_
00061 
00062 /****************************************************************************/
00063 
00064 #if defined (__cplusplus)
00065 
00066 namespace Alignment
00067 {
00068   // Implementing alignof:
00069   // We compute alignof using two separate algorithms, then take their min.
00070 
00071   namespace ffs
00072   {
00073     // alignof (T) must be a power of two which is a factor of sizeof (T).
00074     template <typename T>
00075     struct alignof
00076     {
00077       // Most common programmer interview question!
00078       enum { s = sizeof (T), value = s ^ (s & (s - 1)) };
00079     };
00080   }
00081 
00082   namespace QuantumJump
00083   {
00084     // Put T in a struct, keep adding chars until a "quantum jump" in
00085     // the size occurs.
00086     template <typename T> struct alignof;
00087 
00088     template <int size_diff>
00089     struct helper
00090     {
00091       template <typename T> struct Val { enum { value = size_diff }; };
00092     };
00093 
00094     template <>
00095     struct helper<0>
00096     {
00097       template <typename T> struct Val { enum { value = alignof<T>::value }; };
00098     };
00099 
00100     template <typename T>
00101     struct alignof
00102     {
00103       struct Big { T x; char c; };
00104 
00105       enum { diff = sizeof (Big) - sizeof (T),
00106              value = helper<diff>::template Val<Big>::value };
00107     };
00108 
00109   } // QuantumJump
00110 
00111   template <typename T>
00112   struct alignof
00113   {
00114     enum { x = QuantumJump::alignof<T>::value,
00115            y = ffs::alignof<T>::value,
00116            value = x < y ? x : y };
00117   };
00118 
00119   // ----------------------------------------------------------------
00120 
00121   namespace POD
00122   {
00123     // Implementing alignpod:
00124     // We look for a POD type with the same alignment as a given C++ type T.
00125     // We first check a list of fundamental types.
00126     // In the unlikely event that that fails,
00127     // we check pointers to those types and structs containing those types.
00128 
00129     template <typename T, typename U>
00130     struct equally_aligned
00131     {
00132       enum { value = ((int) alignof<T>::value ==
00133                       (int) alignof<U>::value) };
00134     };
00135 
00136     enum { TYPES_COUNT = 10 };
00137 
00138     template <int n> struct types;
00139 
00140     struct Unknown;
00141 
00142     template <bool POINTERIFY, bool STRUCTIFY>
00143     struct types_helper
00144     {
00145       // This definition should be unnecessary, but makes MSVC happy
00146       template <int index> struct Val { typedef char Type; };
00147     };
00148 
00149     template <>
00150     struct types_helper<true, false>
00151     {
00152       template <int index>
00153       struct Val
00154       {
00155         typedef typename types<index - (1 * TYPES_COUNT)>::Type BaseType;
00156         typedef BaseType* Type;
00157       };
00158     };
00159 
00160     template <>
00161     struct types_helper<false, true>
00162     {
00163       template <int index>
00164       struct Val
00165       {
00166         typedef typename types<index - (2 * TYPES_COUNT)>::Type BaseType;
00167         struct Type { BaseType t; };
00168       };
00169     };
00170 
00171     template <int n>
00172     struct types
00173     {
00174       enum { pointerify = ((n >= 1 * TYPES_COUNT) && (n < 2 * TYPES_COUNT)) };
00175       enum { structify  = ((n >= 2 * TYPES_COUNT) && (n < 3 * TYPES_COUNT)) };
00176 
00177       typedef typename
00178       types_helper<pointerify, structify>::template Val<n>::Type
00179       Type;
00180     };
00181     template <> struct types<0> { typedef char          Type; };
00182     template <> struct types<1> { typedef short         Type; };
00183     template <> struct types<2> { typedef int           Type; };
00184     template <> struct types<3> { typedef long          Type; };
00185     template <> struct types<4> { typedef float         Type; };
00186     template <> struct types<5> { typedef double        Type; };
00187     template <> struct types<6> { typedef long double   Type; };
00188     template <> struct types<7> { typedef void*         Type; };
00189     template <> struct types<8> { typedef void (*Type) (void); };
00190     template <> struct types<9> { typedef Unknown (Unknown::*Type) (Unknown);};
00191 
00192     namespace LinearSearch
00193     {
00194       template <bool EQUALLY_ALIGNED> struct helper;
00195 
00196       template <>
00197       struct helper<true>
00198       {
00199         template <typename T, int index>
00200         struct Val
00201         {
00202           typedef typename types<index>::Type Type;
00203         };
00204       };
00205 
00206       template <typename T, int index>
00207       struct alignpod
00208       {
00209         typedef typename types<index>::Type Candidate;
00210         enum { EQUALLY_ALIGNED = equally_aligned<T,Candidate>::value };
00211 
00212         typedef typename
00213         helper<EQUALLY_ALIGNED>::template Val<T,index>::Type
00214         Type;
00215       };
00216 
00217       template <>
00218       struct helper<false>
00219       {
00220         template <typename T, int index>
00221         struct Val
00222         {
00223           typedef typename alignpod<T, index+1>::Type Type;
00224         };
00225       };
00226 
00227     } // LinearSearch
00228 
00229   } // POD
00230 
00231   template <typename T>
00232   struct alignpod
00233   {
00234     typedef typename POD::LinearSearch::alignpod<T,0>::Type Type;
00235   };
00236 } // Alignment
00237 
00238 #endif /* C++ */
00239 
00240 /****************************************************************************/
00241 
00242 /* gcc has an extension that gives us exactly what we want.
00243    We would use this in production code.
00244 
00245   #if defined (__GNUC__) && (__GNUC__ >= 2)
00246   #define ALIGNOF(type) __alignof__ (type)
00247 */
00248 
00249 /* The following works with all known C++ compilers for POD types.
00250    It doesn't have the "inside out" declaration bug C does.
00251    But C++ forbids the use of offsetof with non-POD types.
00252 
00253   template<typename T> struct alignment_trick { char c; T member; };
00254   #define ALIGNOF(type) offsetof (alignment_trick<type>, member)
00255 */
00256 
00257 
00258 /* ALIGNOF (type)
00259    Return alignment of TYPE. */
00260 #if defined (__cplusplus) /* C++ */
00261 #define ALIGNOF(type) Alignment::alignof<type>::value
00262 #else /* C */
00263 /* The following is mostly portable, except that:
00264    - It doesn't work for inside out declarations like void (*) (void).
00265      (so just call ALIGNOF with a typedef'ed name)
00266    - It doesn't work with C++, not even with fundamental types.
00267      The C++ committee has decreed:
00268      "Types must be declared in declarations, not in expressions." */
00269 #define ALIGNOF(type) offsetof (struct { char c; type member; }, member)
00270 #endif
00271 
00272 
00273 /* ALIGNOF_POD_TYPE (type)
00274    Return a POD (Plain Ol' Data) type with the same alignment as TYPE. */
00275 #if defined (__cplusplus) /* C++ */
00276 #define ALIGN_POD_TYPE(type) Alignment::alignpod<type>::Type
00277 #else
00278 #define ALIGN_POD_TYPE(type) type
00279 #endif
00280 
00281 
00282 /****************************************************************************/
00283 
00284 #endif // Recursive inclusion guard
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines