1 //===- Layout.h -----------------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 // Convenience macros for obtaining offsets of members in structs.
10 //
11 // Usage:
12 //
13 //   #define FOR_EACH_FOO_FIELD(DO) \
14 //     DO(Ptr, bar)                 \
15 //     DO(uint32_t, baz)            \
16 //   CREATE_LAYOUT_CLASS(Foo, FOR_EACH_FOO_FIELD)
17 //   #undef FOR_EACH_FOO_FIELD
18 //
19 // This will generate
20 //
21 //   struct FooLayout {
22 //     uint32_t barOffset;
23 //     uint32_t bazOffset;
24 //     uint32_t totalSize;
25 //
26 //     FooLayout(size_t wordSize) {
27 //       if (wordSize == 8)
28 //         init<uint64_t>();
29 //       else {
30 //         assert(wordSize == 4);
31 //         init<uint32_t>();
32 //       }
33 //     }
34 //
35 //   private:
36 //     template <class Ptr> void init() {
37 //       FOR_EACH_FIELD(_INIT_OFFSET);
38 //       barOffset = offsetof(Layout<Ptr>, bar);
39 //       bazOffset = offsetof(Layout<Ptr>, baz);
40 //       totalSize = sizeof(Layout<Ptr>);
41 //     }
42 //     template <class Ptr> struct Layout {
43 //       Ptr bar;
44 //       uint32_t baz;
45 //     };
46 //   };
47 
48 #define _OFFSET_FOR_FIELD(_, name) uint32_t name##Offset;
49 #define _INIT_OFFSET(type, name) name##Offset = offsetof(Layout<Ptr>, name);
50 #define _LAYOUT_ENTRY(type, name) type name;
51 
52 #define CREATE_LAYOUT_CLASS(className, FOR_EACH_FIELD)                         \
53   struct className##Layout {                                                   \
54     FOR_EACH_FIELD(_OFFSET_FOR_FIELD)                                          \
55     uint32_t totalSize;                                                        \
56                                                                                \
57     className##Layout(size_t wordSize) {                                       \
58       if (wordSize == 8)                                                       \
59         init<uint64_t>();                                                      \
60       else {                                                                   \
61         assert(wordSize == 4);                                                 \
62         init<uint32_t>();                                                      \
63       }                                                                        \
64     }                                                                          \
65                                                                                \
66   private:                                                                     \
67     template <class Ptr> void init() {                                         \
68       FOR_EACH_FIELD(_INIT_OFFSET);                                            \
69       totalSize = sizeof(Layout<Ptr>);                                         \
70     }                                                                          \
71     template <class Ptr> struct Layout {                                       \
72       FOR_EACH_FIELD(_LAYOUT_ENTRY)                                            \
73     };                                                                         \
74   }
75