Open64 (mfef90, whirl2f, and IR tools)
TAG: version-openad; SVN changeset: 916
|
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