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