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