Jez Ng 453102a028 [lld-macho][re-land] Warn on method name collisions from category definitions
This implements ld64's checks for duplicate method names in categories &
classes.

In addition, this sets us up for implementing Obj-C category merging.
This diff handles the most of the parsing work; what's left is rewriting
those category / class structures.

Numbers for chromium_framework:

             base           diff           difference (95% CI)
  sys_time   2.182 ± 0.027  2.200 ± 0.047  [  -0.2% ..   +1.8%]
  user_time  6.451 ± 0.034  6.479 ± 0.062  [  -0.0% ..   +0.9%]
  wall_time  6.841 ± 0.048  6.885 ± 0.105  [  -0.1% ..   +1.4%]
  samples    33             22

Fixes https://github.com/llvm/llvm-project/issues/54912.

Issues seen with the previous land will be fixed in the next commit.

Reviewed By: #lld-macho, thevinster, oontvoo

Differential Revision: https://reviews.llvm.org/D142916
2023-03-30 14:33:42 -04:00

75 lines
3.2 KiB
C++

//===- Layout.h -----------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
// Convenience macros for obtaining offsets of members in structs.
//
// Usage:
//
// #define FOR_EACH_FOO_FIELD(DO) \
// DO(Ptr, bar) \
// DO(uint32_t, baz) \
// CREATE_LAYOUT_CLASS(Foo, FOR_EACH_FOO_FIELD)
// #undef FOR_EACH_FOO_FIELD
//
// This will generate
//
// struct FooLayout {
// uint32_t barOffset;
// uint32_t bazOffset;
// uint32_t totalSize;
//
// FooLayout(size_t wordSize) {
// if (wordSize == 8)
// init<uint64_t>();
// else {
// assert(wordSize == 4);
// init<uint32_t>();
// }
// }
//
// private:
// template <class Ptr> void init() {
// FOR_EACH_FIELD(_INIT_OFFSET);
// barOffset = offsetof(Layout<Ptr>, bar);
// bazOffset = offsetof(Layout<Ptr>, baz);
// totalSize = sizeof(Layout<Ptr>);
// }
// template <class Ptr> struct Layout {
// Ptr bar;
// uint32_t baz;
// };
// };
#define _OFFSET_FOR_FIELD(_, name) uint32_t name##Offset;
#define _INIT_OFFSET(type, name) name##Offset = offsetof(Layout<Ptr>, name);
#define _LAYOUT_ENTRY(type, name) type name;
#define CREATE_LAYOUT_CLASS(className, FOR_EACH_FIELD) \
struct className##Layout { \
FOR_EACH_FIELD(_OFFSET_FOR_FIELD) \
uint32_t totalSize; \
\
className##Layout(size_t wordSize) { \
if (wordSize == 8) \
init<uint64_t>(); \
else { \
assert(wordSize == 4); \
init<uint32_t>(); \
} \
} \
\
private: \
template <class Ptr> void init() { \
FOR_EACH_FIELD(_INIT_OFFSET); \
totalSize = sizeof(Layout<Ptr>); \
} \
template <class Ptr> struct Layout { \
FOR_EACH_FIELD(_LAYOUT_ENTRY) \
}; \
}