1/*
2 * Copyright (c) 2007-2008 The Regents of The University of Michigan
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 * Authors: Gabe Black
29 */
30
31#ifndef __BASE_BITUNION_HH__
32#define __BASE_BITUNION_HH__
33
34#include <functional>
35#include <iostream>
36#include <type_traits>
37#include <typeinfo>
38
39#include "base/bitfield.hh"
40
41//      The following implements the BitUnion system of defining bitfields
42//on top of an underlying class. This is done through the pervasive use of
43//both named and unnamed unions which all contain the same actual storage.
44//Since they're unioned with each other, all of these storage locations
45//overlap. This allows all of the bitfields to manipulate the same data
46//without having to have access to each other. More details are provided with
47//the individual components.
48
49//This class wraps around another which defines getter/setter functions which
50//manipulate the underlying data. The type of the underlying data and the type
51//of the bitfield itself are inferred from the argument types of the setter
52//function.
53template<class Base>
54class BitfieldTypeImpl : public Base
55{
56    static_assert(std::is_empty<Base>::value,
57                  "Bitfield base class must be empty.");
58
59  private:
60
61    struct TypeDeducer
62    {
63        template<typename>
64        struct T;
65
66        template<typename C, typename Type1, typename Type2>
67        struct T<void (C::*)(Type1 &, Type2)>
68        {
69            typedef Type1 Storage;
70            typedef Type2 Type;
71        };
72
73        struct Wrapper : public Base
74        {
75            using Base::setter;
76        };
77
78        typedef typename T<decltype(&Wrapper::setter)>::Storage Storage;
79        typedef typename T<decltype(&Wrapper::setter)>::Type Type;
80    };
81
82  protected:
83    typedef typename TypeDeducer::Storage Storage;
84    typedef typename TypeDeducer::Type Type;
85
86    Type getter(const Storage &storage) const = delete;
87    void setter(Storage &storage, Type val) = delete;
88
89    Storage __storage;
90
91    operator Type () const
92    {
93        return Base::getter(__storage);
94    }
95
96    Type
97    operator=(const Type val)
98    {
99        Base::setter(__storage, val);
100        return val;
101    }
102
103    Type
104    operator=(BitfieldTypeImpl<Base> const & other)
105    {
106        return *this = (Type)other;
107    }
108};
109
110//A wrapper for the above class which allows setting and getting.
111template<class Base>
112class BitfieldType : public BitfieldTypeImpl<Base>
113{
114  protected:
115    using Impl = BitfieldTypeImpl<Base>;
116    using typename Impl::Type;
117
118  public:
119    operator Type () const { return Impl::operator Type(); }
120    Type operator=(const Type val) { return Impl::operator=(val); }
121    Type
122    operator=(BitfieldType<Base> const & other)
123    {
124        return Impl::operator=(other);
125    }
126};
127
128//A wrapper which only supports getting.
129template<class Base>
130class BitfieldROType : public BitfieldTypeImpl<Base>
131{
132  public:
133    using Impl = BitfieldTypeImpl<Base>;
134    using typename Impl::Type;
135
136    Type operator=(BitfieldROType<Base> const &other) = delete;
137    operator Type () const { return Impl::operator Type(); }
138};
139
140//A wrapper which only supports setting.
141template <class Base>
142class BitfieldWOType : public BitfieldTypeImpl<Base>
143{
144  protected:
145    using Impl = BitfieldTypeImpl<Base>;
146    using typename Impl::Type;
147
148  public:
149    Type operator=(const Type val) { return Impl::operator=(val); }
150    Type
151    operator=(BitfieldWOType<Base> const & other)
152    {
153        return Impl::operator=(other);
154    }
155};
156
157//This namespace is for classes which implement the backend of the BitUnion
158//stuff. Don't use any of these directly.
159namespace BitfieldBackend
160{
161    template<class Storage, int first, int last>
162    class Unsigned
163    {
164        static_assert(first >= last,
165                      "Bitfield ranges must be specified as <msb, lsb>");
166
167      protected:
168        uint64_t
169        getter(const Storage &storage) const
170        {
171            return bits(storage, first, last);
172        }
173
174        void
175        setter(Storage &storage, uint64_t val)
176        {
177            replaceBits(storage, first, last, val);
178        }
179    };
180
181    template<class Storage, int first, int last>
182    class Signed
183    {
184        static_assert(first >= last,
185                      "Bitfield ranges must be specified as <msb, lsb>");
186
187      protected:
188        int64_t
189        getter(const Storage &storage) const
190        {
191            return sext<first - last + 1>(bits(storage, first, last));
192        }
193
194        void
195        setter(Storage &storage, int64_t val)
196        {
197            replaceBits(storage, first, last, val);
198        }
199    };
200
201    //This class contains the basic bitfield types which are automatically
202    //available within a BitUnion. They inherit their Storage type from the
203    //containing BitUnion.
204    template<class Storage>
205    class BitfieldTypes
206    {
207      protected:
208
209        template<int first, int last=first>
210        using Bitfield = BitfieldType<Unsigned<Storage, first, last> >;
211        template<int first, int last=first>
212        using BitfieldRO =
213                BitfieldROType<Unsigned<Storage, first, last> >;
214        template<int first, int last=first>
215        using BitfieldWO =
216                BitfieldWOType<Unsigned<Storage, first, last> >;
217
218        template<int first, int last=first>
219        using SignedBitfield =
220                BitfieldType<Signed<Storage, first, last> >;
221        template<int first, int last=first>
222        using SignedBitfieldRO =
223                BitfieldROType<Signed<Storage, first, last> >;
224        template<int first, int last=first>
225        using SignedBitfieldWO =
226                BitfieldWOType<Signed<Storage, first, last> >;
227    };
228
229    //When a BitUnion is set up, an underlying class is created which holds
230    //the actual union. This class then inherits from it, and provids the
231    //implementations for various operators. Setting things up this way
232    //prevents having to redefine these functions in every different BitUnion
233    //type. More operators could be implemented in the future, as the need
234    //arises.
235    template <class Base>
236    class BitUnionOperators : public Base
237    {
238        static_assert(sizeof(Base) == sizeof(typename Base::__StorageType),
239                      "BitUnion larger than its storage type.");
240
241      public:
242        BitUnionOperators(typename Base::__StorageType const &val)
243        {
244            Base::__storage = val;
245        }
246
247        BitUnionOperators() {}
248
249        operator const typename Base::__StorageType () const
250        {
251            return Base::__storage;
252        }
253
254        typename Base::__StorageType
255        operator=(typename Base::__StorageType const &val)
256        {
257            Base::__storage = val;
258            return val;
259        }
260
261        typename Base::__StorageType
262        operator=(BitUnionOperators const &other)
263        {
264            Base::__storage = other;
265            return Base::__storage;
266        }
267
268        bool
269        operator<(Base const &base) const
270        {
271            return Base::__storage < base.__storage;
272        }
273
274        bool
275        operator==(Base const &base) const
276        {
277            return Base::__storage == base.__storage;
278        }
279    };
280}
281
282//This macro is a backend for other macros that specialize it slightly.
283//First, it creates/extends a namespace "BitfieldUnderlyingClasses" and
284//sticks the class which has the actual union in it, which
285//BitfieldOperators above inherits from. Putting these classes in a special
286//namespace ensures that there will be no collisions with other names as long
287//as the BitUnion names themselves are all distinct and nothing else uses
288//the BitfieldUnderlyingClasses namespace, which is unlikely. The class itself
289//creates a typedef of the "type" parameter called __StorageType. This allows
290//the type to propagate outside of the macro itself in a controlled way.
291//Finally, the base storage is defined which BitfieldOperators will refer to
292//in the operators it defines. This macro is intended to be followed by
293//bitfield definitions which will end up inside it's union. As explained
294//above, these is overlayed the __storage member in its entirety by each of the
295//bitfields which are defined in the union, creating shared storage with no
296//overhead.
297#define __BitUnion(type, name) \
298    class BitfieldUnderlyingClasses##name : \
299        public BitfieldBackend::BitfieldTypes<type> \
300    { \
301      protected: \
302        typedef type __StorageType; \
303        friend BitfieldBackend::BitUnionBaseType< \
304            BitfieldBackend::BitUnionOperators< \
305                BitfieldUnderlyingClasses##name> >; \
306        friend BitfieldBackend::BitUnionBaseType< \
307                BitfieldUnderlyingClasses##name>; \
308      public: \
309        union { \
310            type __storage;
311
312//This closes off the class and union started by the above macro. It is
313//followed by a typedef which makes "name" refer to a BitfieldOperator
314//class inheriting from the class and union just defined, which completes
315//building up the type for the user.
316#define EndBitUnion(name) \
317        }; \
318    }; \
319    typedef BitfieldBackend::BitUnionOperators< \
320        BitfieldUnderlyingClasses##name> name;
321
322//This sets up a bitfield which has other bitfields nested inside of it. The
323//__storage member functions like the "underlying storage" of the top level
324//BitUnion. Like everything else, it overlays with the top level storage, so
325//making it a regular bitfield type makes the entire thing function as a
326//regular bitfield when referred to by itself.
327#define __SubBitUnion(name, fieldType, ...) \
328    class \
329    { \
330      public: \
331        union { \
332            fieldType<__VA_ARGS__> __storage;
333
334//This closes off the union created above and gives it a name. Unlike the top
335//level BitUnion, we're interested in creating an object instead of a type.
336//The operators are defined in the macro itself instead of a class for
337//technical reasons. If someone determines a way to move them to one, please
338//do so.
339#define EndSubBitUnion(name) \
340        }; \
341        inline operator __StorageType () const \
342        { return __storage; } \
343        \
344        inline __StorageType operator = (const __StorageType & _storage) \
345        { return __storage = _storage;} \
346    } name;
347
348//Regular bitfields
349//These define macros for read/write regular bitfield based subbitfields.
350#define SubBitUnion(name, first, last) \
351    __SubBitUnion(name, Bitfield, first, last)
352
353//Regular bitfields
354//These define macros for read/write regular bitfield based subbitfields.
355#define SignedSubBitUnion(name, first, last) \
356    __SubBitUnion(name, SignedBitfield, first, last)
357
358//Use this to define an arbitrary type overlayed with bitfields.
359#define BitUnion(type, name) __BitUnion(type, name)
360
361//Use this to define conveniently sized values overlayed with bitfields.
362#define BitUnion64(name) __BitUnion(uint64_t, name)
363#define BitUnion32(name) __BitUnion(uint32_t, name)
364#define BitUnion16(name) __BitUnion(uint16_t, name)
365#define BitUnion8(name) __BitUnion(uint8_t, name)
366
367
368//These templates make it possible to define other templates related to
369//BitUnions without having to refer to internal typedefs or the BitfieldBackend
370//namespace.
371
372//To build a template specialization which works for all BitUnions, accept a
373//template argument T, and then use BitUnionType<T> as an argument in the
374//template. To refer to the basic type the BitUnion wraps, use
375//BitUnionBaseType<T>.
376
377//For example:
378//template <typename T>
379//void func(BitUnionType<T> u) { BitUnionBaseType<T> b = u; }
380
381//Also, BitUnionBaseType can be used on a BitUnion type directly.
382
383template <typename T>
384using BitUnionType = BitfieldBackend::BitUnionOperators<T>;
385
386namespace BitfieldBackend
387{
388    template<typename T>
389    struct BitUnionBaseType
390    {
391        typedef typename BitUnionType<T>::__StorageType Type;
392    };
393
394    template<typename T>
395    struct BitUnionBaseType<BitUnionType<T> >
396    {
397        typedef typename BitUnionType<T>::__StorageType Type;
398    };
399}
400
401template <typename T>
402using BitUnionBaseType = typename BitfieldBackend::BitUnionBaseType<T>::Type;
403
404
405//An STL style hash structure for hashing BitUnions based on their base type.
406namespace std
407{
408    template <typename T>
409    struct hash<BitUnionType<T> > : public hash<BitUnionBaseType<T> >
410    {
411        size_t
412        operator() (const BitUnionType<T> &val) const
413        {
414            return hash<BitUnionBaseType<T> >::operator()(val);
415        }
416    };
417}
418
419
420namespace BitfieldBackend
421{
422
423    template<typename T>
424    static inline std::ostream &
425    bitfieldBackendPrinter(std::ostream &os, const T &t)
426    {
427        os << t;
428        return os;
429    }
430
431    //Since BitUnions are generally numerical values and not character codes,
432    //these specializations attempt to ensure that they get cast to integers
433    //of the appropriate type before printing.
434    template <>
435    inline std::ostream &
436    bitfieldBackendPrinter(std::ostream &os, const char &t)
437    {
438        os << (int)t;
439        return os;
440    }
441
442    template <>
443    inline std::ostream &
444    bitfieldBackendPrinter(std::ostream &os, const unsigned char &t)
445    {
446        os << (unsigned int)t;
447        return os;
448    }
449}
450
451//A default << operator which casts a bitunion to its underlying type and
452//passes it to BitfieldBackend::bitfieldBackendPrinter.
453template <typename T>
454std::ostream &
455operator << (std::ostream &os, const BitUnionType<T> &bu)
456{
457    return BitfieldBackend::bitfieldBackendPrinter(
458            os, (BitUnionBaseType<T>)bu);
459}
460
461#endif // __BASE_BITUNION_HH__
462