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