[lld] 5373daa - Revert "[lld-macho] Implement ObjC category merging (-objc_category_merging) (#82928)"
Kyungwoo Lee via llvm-commits
llvm-commits at lists.llvm.org
Mon Mar 18 17:18:37 PDT 2024
Author: Kyungwoo Lee
Date: 2024-03-18T17:16:52-07:00
New Revision: 5373daad9492e157c0c1ad496334f5dfd78d7da0
URL: https://github.com/llvm/llvm-project/commit/5373daad9492e157c0c1ad496334f5dfd78d7da0
DIFF: https://github.com/llvm/llvm-project/commit/5373daad9492e157c0c1ad496334f5dfd78d7da0.diff
LOG: Revert "[lld-macho] Implement ObjC category merging (-objc_category_merging) (#82928)"
This reverts commit ece2903ce730392e5236d27f1f387fa8067fcb1b, https://github.com/llvm/llvm-project/pull/82928.
https://github.com/llvm/llvm-project/pull/82928
Added:
Modified:
lld/MachO/Driver.cpp
lld/MachO/InputSection.h
lld/MachO/ObjC.cpp
lld/MachO/ObjC.h
lld/MachO/Options.td
Removed:
lld/test/MachO/objc-category-merging-complete-test.s
lld/test/MachO/objc-category-merging-extern-class-minimal.s
################################################################################
diff --git a/lld/MachO/Driver.cpp b/lld/MachO/Driver.cpp
index 36248925d65ad2..9edb6b9c60a1fe 100644
--- a/lld/MachO/Driver.cpp
+++ b/lld/MachO/Driver.cpp
@@ -1437,8 +1437,6 @@ bool link(ArrayRef<const char *> argsArr, llvm::raw_ostream &stdoutOS,
resetOutputSegments();
resetWriter();
InputFile::resetIdCount();
-
- objc::doCleanup();
};
ctx->e.logName = args::getFilenameWithoutExe(argsArr[0]);
@@ -1981,16 +1979,9 @@ bool link(ArrayRef<const char *> argsArr, llvm::raw_ostream &stdoutOS,
if (config->deadStrip)
markLive();
- // Categories are not subject to dead-strip. The __objc_catlist section is
- // marked as NO_DEAD_STRIP and that propagates into all category data.
if (args.hasArg(OPT_check_category_conflicts))
objc::checkCategories();
- // Category merging uses "->live = false" to erase old category data, so
- // it has to run after dead-stripping (markLive).
- if (args.hasArg(OPT_objc_category_merging, OPT_no_objc_category_merging))
- objc::mergeCategories();
-
// ICF assumes that all literals have been folded already, so we must run
// foldIdenticalLiterals before foldIdenticalSections.
foldIdenticalLiterals();
diff --git a/lld/MachO/InputSection.h b/lld/MachO/InputSection.h
index b25f0638f4c6cb..becb01017d633a 100644
--- a/lld/MachO/InputSection.h
+++ b/lld/MachO/InputSection.h
@@ -93,9 +93,9 @@ class InputSection {
// .subsections_via_symbols, there is typically only one element here.
llvm::TinyPtrVector<Defined *> symbols;
+protected:
const Section §ion;
-protected:
const Defined *getContainingSymbol(uint64_t off) const;
};
diff --git a/lld/MachO/ObjC.cpp b/lld/MachO/ObjC.cpp
index 9b2446360e4f7f..67254ec53a2145 100644
--- a/lld/MachO/ObjC.cpp
+++ b/lld/MachO/ObjC.cpp
@@ -7,19 +7,16 @@
//===----------------------------------------------------------------------===//
#include "ObjC.h"
-#include "ConcatOutputSection.h"
#include "InputFiles.h"
#include "InputSection.h"
#include "Layout.h"
#include "OutputSegment.h"
-#include "SyntheticSections.h"
#include "Target.h"
#include "lld/Common/ErrorHandler.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/BinaryFormat/MachO.h"
#include "llvm/Bitcode/BitcodeReader.h"
-#include "llvm/Support/TimeProfiler.h"
using namespace llvm;
using namespace llvm::MachO;
@@ -81,8 +78,7 @@ namespace {
DO(Ptr, classMethods) \
DO(Ptr, protocols) \
DO(Ptr, instanceProps) \
- DO(Ptr, classProps) \
- DO(uint32_t, size)
+ DO(Ptr, classProps)
CREATE_LAYOUT_CLASS(Category, FOR_EACH_CATEGORY_FIELD);
@@ -116,19 +112,13 @@ CREATE_LAYOUT_CLASS(ROClass, FOR_EACH_RO_CLASS_FIELD);
#undef FOR_EACH_RO_CLASS_FIELD
#define FOR_EACH_LIST_HEADER(DO) \
- DO(uint32_t, structSize) \
- DO(uint32_t, structCount)
+ DO(uint32_t, size) \
+ DO(uint32_t, count)
CREATE_LAYOUT_CLASS(ListHeader, FOR_EACH_LIST_HEADER);
#undef FOR_EACH_LIST_HEADER
-#define FOR_EACH_PROTOCOL_LIST_HEADER(DO) DO(Ptr, protocolCount)
-
-CREATE_LAYOUT_CLASS(ProtocolListHeader, FOR_EACH_PROTOCOL_LIST_HEADER);
-
-#undef FOR_EACH_PROTOCOL_LIST_HEADER
-
#define FOR_EACH_METHOD(DO) \
DO(Ptr, name) \
DO(Ptr, type) \
@@ -321,8 +311,6 @@ void ObjcCategoryChecker::parseClass(const Defined *classSym) {
}
void objc::checkCategories() {
- TimeTraceScope timeScope("ObjcCategoryChecker");
-
ObjcCategoryChecker checker;
for (const InputSection *isec : inputSections) {
if (isec->getName() == section_names::objcCatList)
@@ -332,905 +320,3 @@ void objc::checkCategories() {
}
}
}
-
-namespace {
-
-class ObjcCategoryMerger {
- // Information about an input category
- struct InfoInputCategory {
- ConcatInputSection *catListIsec;
- ConcatInputSection *catBodyIsec;
- uint32_t offCatListIsec = 0;
-
- bool wasMerged = false;
- };
-
- // To write new (merged) categories or classes, we will try make limited
- // assumptions about the alignment and the sections the various class/category
- // info are stored in and . So we'll just reuse the same sections and
- // alignment as already used in existing (input) categories. To do this we
- // have InfoCategoryWriter which contains the various sections that the
- // generated categories will be written to.
- template <typename T> struct InfoWriteSection {
- bool valid = false; // Data has been successfully collected from input
- uint32_t align = 0;
- Section *inputSection;
- Reloc relocTemplate;
- T *outputSection;
- };
-
- struct InfoCategoryWriter {
- InfoWriteSection<ConcatOutputSection> catListInfo;
- InfoWriteSection<ConcatOutputSection> catBodyInfo;
- InfoWriteSection<CStringSection> catNameInfo;
- InfoWriteSection<ConcatOutputSection> catPtrListInfo;
- };
-
- // Information about a pointer list in the original categories (method lists,
- // protocol lists, etc)
- struct PointerListInfo {
- PointerListInfo(const char *_categoryPrefix, uint32_t _categoryOffset,
- uint32_t _pointersPerStruct)
- : categoryPrefix(_categoryPrefix), categoryOffset(_categoryOffset),
- pointersPerStruct(_pointersPerStruct) {}
- const char *categoryPrefix;
- uint32_t categoryOffset = 0;
-
- uint32_t pointersPerStruct = 0;
-
- uint32_t structSize = 0;
- uint32_t structCount = 0;
-
- std::vector<Symbol *> allPtrs;
- };
-
- // Full information about all the categories that extend a class. This will
- // include all the additional methods, protocols, and properties that are
- // contained in all the categories that extend a particular class.
- struct ClassExtensionInfo {
- ClassExtensionInfo(CategoryLayout &_catLayout) : catLayout(_catLayout){};
-
- // Merged names of containers. Ex: base|firstCategory|secondCategory|...
- std::string mergedContainerName;
- std::string baseClassName;
- Symbol *baseClass = nullptr;
- CategoryLayout &catLayout;
-
- // In case we generate new data, mark the new data as belonging to this file
- ObjFile *objFileForMergeData = nullptr;
-
- PointerListInfo instanceMethods = {
- objc::symbol_names::categoryInstanceMethods,
- /*_categoryOffset=*/catLayout.instanceMethodsOffset,
- /*pointersPerStruct=*/3};
- PointerListInfo classMethods = {
- objc::symbol_names::categoryClassMethods,
- /*_categoryOffset=*/catLayout.classMethodsOffset,
- /*pointersPerStruct=*/3};
- PointerListInfo protocols = {objc::symbol_names::categoryProtocols,
- /*_categoryOffset=*/catLayout.protocolsOffset,
- /*pointersPerStruct=*/0};
- PointerListInfo instanceProps = {
- objc::symbol_names::listProprieties,
- /*_categoryOffset=*/catLayout.instancePropsOffset,
- /*pointersPerStruct=*/2};
- PointerListInfo classProps = {
- objc::symbol_names::klassPropList,
- /*_categoryOffset=*/catLayout.classPropsOffset,
- /*pointersPerStruct=*/2};
- };
-
-public:
- ObjcCategoryMerger(std::vector<ConcatInputSection *> &_allInputSections);
- void doMerge();
- static void doCleanup();
-
-private:
- void collectAndValidateCategoriesData();
- void
- mergeCategoriesIntoSingleCategory(std::vector<InfoInputCategory> &categories);
-
- void eraseISec(ConcatInputSection *isec);
- void eraseMergedCategories();
-
- void generateCatListForNonErasedCategories(
- std::map<ConcatInputSection *, std::set<uint64_t>>
- catListToErasedOffsets);
- template <typename T>
- void collectSectionWriteInfoFromIsec(const InputSection *isec,
- InfoWriteSection<T> &catWriteInfo);
- void collectCategoryWriterInfoFromCategory(const InfoInputCategory &catInfo);
- void parseCatInfoToExtInfo(const InfoInputCategory &catInfo,
- ClassExtensionInfo &extInfo);
-
- void parseProtocolListInfo(const ConcatInputSection *isec, uint32_t secOffset,
- PointerListInfo &ptrList);
-
- void parsePointerListInfo(const ConcatInputSection *isec, uint32_t secOffset,
- PointerListInfo &ptrList);
-
- void emitAndLinkPointerList(Defined *parentSym, uint32_t linkAtOffset,
- const ClassExtensionInfo &extInfo,
- const PointerListInfo &ptrList);
-
- void emitAndLinkProtocolList(Defined *parentSym, uint32_t linkAtOffset,
- const ClassExtensionInfo &extInfo,
- const PointerListInfo &ptrList);
-
- Defined *emitCategory(const ClassExtensionInfo &extInfo);
- Defined *emitCatListEntrySec(const std::string &forCateogryName,
- const std::string &forBaseClassName,
- ObjFile *objFile);
- Defined *emitCategoryBody(const std::string &name, const Defined *nameSym,
- const Symbol *baseClassSym,
- const std::string &baseClassName, ObjFile *objFile);
- Defined *emitCategoryName(const std::string &name, ObjFile *objFile);
- void createSymbolReference(Defined *refFrom, const Symbol *refTo,
- uint32_t offset, const Reloc &relocTemplate);
- Symbol *tryGetSymbolAtIsecOffset(const ConcatInputSection *isec,
- uint32_t offset);
- Defined *tryGetDefinedAtIsecOffset(const ConcatInputSection *isec,
- uint32_t offset);
- void tryEraseDefinedAtIsecOffset(const ConcatInputSection *isec,
- uint32_t offset);
-
- // Allocate a null-terminated StringRef backed by generatedSectionData
- StringRef newStringData(const char *str);
- // Allocate section data, backed by generatedSectionData
- SmallVector<uint8_t> &newSectionData(uint32_t size);
-
- CategoryLayout catLayout;
- ClassLayout classLayout;
- ROClassLayout roClassLayout;
- ListHeaderLayout listHeaderLayout;
- MethodLayout methodLayout;
- ProtocolListHeaderLayout protocolListHeaderLayout;
-
- InfoCategoryWriter infoCategoryWriter;
- std::vector<ConcatInputSection *> &allInputSections;
- // Map of base class Symbol to list of InfoInputCategory's for it
- DenseMap<const Symbol *, std::vector<InfoInputCategory>> categoryMap;
-
- // Normally, the binary data comes from the input files, but since we're
- // generating binary data ourselves, we use the below array to store it in.
- // Need this to be 'static' so the data survives past the ObjcCategoryMerger
- // object, as the data will be read by the Writer when the final binary is
- // generated.
- static SmallVector<SmallVector<uint8_t>> generatedSectionData;
-};
-
-SmallVector<SmallVector<uint8_t>> ObjcCategoryMerger::generatedSectionData;
-
-ObjcCategoryMerger::ObjcCategoryMerger(
- std::vector<ConcatInputSection *> &_allInputSections)
- : catLayout(target->wordSize), classLayout(target->wordSize),
- roClassLayout(target->wordSize), listHeaderLayout(target->wordSize),
- methodLayout(target->wordSize),
- protocolListHeaderLayout(target->wordSize),
- allInputSections(_allInputSections) {}
-
-// This is a template so that it can be used both for CStringSection and
-// ConcatOutputSection
-template <typename T>
-void ObjcCategoryMerger::collectSectionWriteInfoFromIsec(
- const InputSection *isec, InfoWriteSection<T> &catWriteInfo) {
-
- catWriteInfo.inputSection = const_cast<Section *>(&isec->section);
- catWriteInfo.align = isec->align;
- catWriteInfo.outputSection = dyn_cast_or_null<T>(isec->parent);
-
- assert(catWriteInfo.outputSection &&
- "outputSection may not be null in collectSectionWriteInfoFromIsec.");
-
- if (isec->relocs.size())
- catWriteInfo.relocTemplate = isec->relocs[0];
-
- catWriteInfo.valid = true;
-}
-
-Symbol *
-ObjcCategoryMerger::tryGetSymbolAtIsecOffset(const ConcatInputSection *isec,
- uint32_t offset) {
- const Reloc *reloc = isec->getRelocAt(offset);
-
- if (!reloc)
- return nullptr;
-
- return reloc->referent.get<Symbol *>();
-}
-
-Defined *
-ObjcCategoryMerger::tryGetDefinedAtIsecOffset(const ConcatInputSection *isec,
- uint32_t offset) {
- Symbol *sym = tryGetSymbolAtIsecOffset(isec, offset);
- return dyn_cast_or_null<Defined>(sym);
-}
-
-// Given an ConcatInputSection or CStringInputSection and an offset, if there is
-// a symbol(Defined) at that offset, then erase the symbol (mark it not live)
-void ObjcCategoryMerger::tryEraseDefinedAtIsecOffset(
- const ConcatInputSection *isec, uint32_t offset) {
- const Reloc *reloc = isec->getRelocAt(offset);
-
- if (!reloc)
- return;
-
- Defined *sym = dyn_cast_or_null<Defined>(reloc->referent.get<Symbol *>());
- if (!sym)
- return;
-
- if (auto *cisec = dyn_cast_or_null<ConcatInputSection>(sym->isec))
- eraseISec(cisec);
- else if (auto *csisec = dyn_cast_or_null<CStringInputSection>(sym->isec)) {
- uint32_t totalOffset = sym->value + reloc->addend;
- StringPiece &piece = csisec->getStringPiece(totalOffset);
- piece.live = false;
- } else {
- llvm_unreachable("erased symbol has to be Defined or CStringInputSection");
- }
-}
-
-void ObjcCategoryMerger::collectCategoryWriterInfoFromCategory(
- const InfoInputCategory &catInfo) {
-
- if (!infoCategoryWriter.catListInfo.valid)
- collectSectionWriteInfoFromIsec<ConcatOutputSection>(
- catInfo.catListIsec, infoCategoryWriter.catListInfo);
- if (!infoCategoryWriter.catBodyInfo.valid)
- collectSectionWriteInfoFromIsec<ConcatOutputSection>(
- catInfo.catBodyIsec, infoCategoryWriter.catBodyInfo);
-
- if (!infoCategoryWriter.catNameInfo.valid) {
- lld::macho::Defined *catNameSym =
- tryGetDefinedAtIsecOffset(catInfo.catBodyIsec, catLayout.nameOffset);
- assert(catNameSym && "Category does not have a valid name Symbol");
-
- collectSectionWriteInfoFromIsec<CStringSection>(
- catNameSym->isec, infoCategoryWriter.catNameInfo);
- }
-
- // Collect writer info from all the category lists (we're assuming they all
- // would provide the same info)
- if (!infoCategoryWriter.catPtrListInfo.valid) {
- for (uint32_t off = catLayout.instanceMethodsOffset;
- off <= catLayout.classPropsOffset; off += target->wordSize) {
- if (Defined *ptrList =
- tryGetDefinedAtIsecOffset(catInfo.catBodyIsec, off)) {
- collectSectionWriteInfoFromIsec<ConcatOutputSection>(
- ptrList->isec, infoCategoryWriter.catPtrListInfo);
- // we've successfully collected data, so we can break
- break;
- }
- }
- }
-}
-
-// Parse a protocol list that might be linked to ConcatInputSection at a given
-// offset. The format of the protocol list is
diff erent than other lists (prop
-// lists, method lists) so we need to parse it
diff erently
-void ObjcCategoryMerger::parseProtocolListInfo(const ConcatInputSection *isec,
- uint32_t secOffset,
- PointerListInfo &ptrList) {
- if (!isec || (secOffset + target->wordSize > isec->data.size()))
- assert("Tried to read pointer list beyond protocol section end");
-
- const Reloc *reloc = isec->getRelocAt(secOffset);
- if (!reloc)
- return;
-
- auto *ptrListSym = dyn_cast_or_null<Defined>(reloc->referent.get<Symbol *>());
- assert(ptrListSym && "Protocol list reloc does not have a valid Defined");
-
- // Theoretically protocol count can be either 32b or 64b, depending on
- // platform pointer size, but to simplify implementation we always just read
- // the lower 32b which should be good enough.
- uint32_t protocolCount = *reinterpret_cast<const uint32_t *>(
- ptrListSym->isec->data.data() + listHeaderLayout.structSizeOffset);
-
- ptrList.structCount += protocolCount;
- ptrList.structSize = target->wordSize;
-
- uint32_t expectedListSize =
- (protocolCount * target->wordSize) +
- /*header(count)*/ protocolListHeaderLayout.totalSize +
- /*extra null value*/ target->wordSize;
- assert(expectedListSize == ptrListSym->isec->data.size() &&
- "Protocol list does not match expected size");
-
- uint32_t off = protocolListHeaderLayout.totalSize;
- for (uint32_t inx = 0; inx < protocolCount; ++inx) {
- const Reloc *reloc = ptrListSym->isec->getRelocAt(off);
- assert(reloc && "No reloc found at protocol list offset");
-
- auto *listSym = dyn_cast_or_null<Defined>(reloc->referent.get<Symbol *>());
- assert(listSym && "Protocol list reloc does not have a valid Defined");
-
- ptrList.allPtrs.push_back(listSym);
- off += target->wordSize;
- }
- assert((ptrListSym->isec->getRelocAt(off) == nullptr) &&
- "expected null terminating protocol");
- assert(off + /*extra null value*/ target->wordSize == expectedListSize &&
- "Protocol list end offset does not match expected size");
-}
-
-// Parse a pointer list that might be linked to ConcatInputSection at a given
-// offset. This can be used for instance methods, class methods, instance props
-// and class props since they have the same format.
-void ObjcCategoryMerger::parsePointerListInfo(const ConcatInputSection *isec,
- uint32_t secOffset,
- PointerListInfo &ptrList) {
- assert(ptrList.pointersPerStruct == 2 || ptrList.pointersPerStruct == 3);
- assert(isec && "Trying to parse pointer list from null isec");
- assert(secOffset + target->wordSize <= isec->data.size() &&
- "Trying to read pointer list beyond section end");
-
- const Reloc *reloc = isec->getRelocAt(secOffset);
- if (!reloc)
- return;
-
- auto *ptrListSym = dyn_cast_or_null<Defined>(reloc->referent.get<Symbol *>());
- assert(ptrListSym && "Reloc does not have a valid Defined");
-
- uint32_t thisStructSize = *reinterpret_cast<const uint32_t *>(
- ptrListSym->isec->data.data() + listHeaderLayout.structSizeOffset);
- uint32_t thisStructCount = *reinterpret_cast<const uint32_t *>(
- ptrListSym->isec->data.data() + listHeaderLayout.structCountOffset);
- assert(thisStructSize == ptrList.pointersPerStruct * target->wordSize);
-
- assert(!ptrList.structSize || (thisStructSize == ptrList.structSize));
-
- ptrList.structCount += thisStructCount;
- ptrList.structSize = thisStructSize;
-
- uint32_t expectedListSize =
- listHeaderLayout.totalSize + (thisStructSize * thisStructCount);
- assert(expectedListSize == ptrListSym->isec->data.size() &&
- "Pointer list does not match expected size");
-
- for (uint32_t off = listHeaderLayout.totalSize; off < expectedListSize;
- off += target->wordSize) {
- const Reloc *reloc = ptrListSym->isec->getRelocAt(off);
- assert(reloc && "No reloc found at pointer list offset");
-
- auto *listSym = dyn_cast_or_null<Defined>(reloc->referent.get<Symbol *>());
- assert(listSym && "Reloc does not have a valid Defined");
-
- ptrList.allPtrs.push_back(listSym);
- }
-}
-
-// Here we parse all the information of an input category (catInfo) and
-// append the parsed info into the structure which will contain all the
-// information about how a class is extended (extInfo)
-void ObjcCategoryMerger::parseCatInfoToExtInfo(const InfoInputCategory &catInfo,
- ClassExtensionInfo &extInfo) {
- const Reloc *catNameReloc =
- catInfo.catBodyIsec->getRelocAt(catLayout.nameOffset);
-
- // Parse name
- assert(catNameReloc && "Category does not have a reloc at 'nameOffset'");
-
- // is this the first category we are parsing?
- if (extInfo.mergedContainerName.empty())
- extInfo.objFileForMergeData =
- dyn_cast_or_null<ObjFile>(catInfo.catBodyIsec->getFile());
- else
- extInfo.mergedContainerName += "|";
-
- assert(extInfo.objFileForMergeData &&
- "Expected to already have valid objextInfo.objFileForMergeData");
-
- StringRef catName = getReferentString(*catNameReloc);
- extInfo.mergedContainerName += catName.str();
-
- // Parse base class
- if (!extInfo.baseClass) {
- Symbol *classSym =
- tryGetSymbolAtIsecOffset(catInfo.catBodyIsec, catLayout.klassOffset);
- assert(extInfo.baseClassName.empty());
- extInfo.baseClass = classSym;
- llvm::StringRef classPrefix(objc::symbol_names::klass);
- assert(classSym->getName().starts_with(classPrefix) &&
- "Base class symbol does not start with expected prefix");
- extInfo.baseClassName = classSym->getName().substr(classPrefix.size());
- } else {
- assert((extInfo.baseClass ==
- tryGetSymbolAtIsecOffset(catInfo.catBodyIsec,
- catLayout.klassOffset)) &&
- "Trying to parse category info into container with
diff erent base "
- "class");
- }
-
- parsePointerListInfo(catInfo.catBodyIsec, catLayout.instanceMethodsOffset,
- extInfo.instanceMethods);
-
- parsePointerListInfo(catInfo.catBodyIsec, catLayout.classMethodsOffset,
- extInfo.classMethods);
-
- parseProtocolListInfo(catInfo.catBodyIsec, catLayout.protocolsOffset,
- extInfo.protocols);
-
- parsePointerListInfo(catInfo.catBodyIsec, catLayout.instancePropsOffset,
- extInfo.instanceProps);
-
- parsePointerListInfo(catInfo.catBodyIsec, catLayout.classPropsOffset,
- extInfo.classProps);
-}
-
-// Generate a protocol list (including header) and link it into the parent at
-// the specified offset.
-void ObjcCategoryMerger::emitAndLinkProtocolList(
- Defined *parentSym, uint32_t linkAtOffset,
- const ClassExtensionInfo &extInfo, const PointerListInfo &ptrList) {
- if (ptrList.allPtrs.empty())
- return;
-
- assert(ptrList.allPtrs.size() == ptrList.structCount);
-
- uint32_t bodySize = (ptrList.structCount * target->wordSize) +
- /*header(count)*/ protocolListHeaderLayout.totalSize +
- /*extra null value*/ target->wordSize;
- llvm::ArrayRef<uint8_t> bodyData = newSectionData(bodySize);
-
- // This theoretically can be either 32b or 64b, but writing just the first 32b
- // is good enough
- const uint32_t *ptrProtoCount = reinterpret_cast<const uint32_t *>(
- bodyData.data() + protocolListHeaderLayout.protocolCountOffset);
-
- *const_cast<uint32_t *>(ptrProtoCount) = ptrList.allPtrs.size();
-
- ConcatInputSection *listSec = make<ConcatInputSection>(
- *infoCategoryWriter.catPtrListInfo.inputSection, bodyData,
- infoCategoryWriter.catPtrListInfo.align);
- listSec->parent = infoCategoryWriter.catPtrListInfo.outputSection;
- listSec->live = true;
- allInputSections.push_back(listSec);
-
- listSec->parent = infoCategoryWriter.catPtrListInfo.outputSection;
-
- std::string symName = ptrList.categoryPrefix;
- symName += extInfo.baseClassName + "_$_(" + extInfo.mergedContainerName + ")";
-
- Defined *ptrListSym = make<Defined>(
- newStringData(symName.c_str()), /*file=*/parentSym->getObjectFile(),
- listSec, /*value=*/0, bodyData.size(), /*isWeakDef=*/false,
- /*isExternal=*/false, /*isPrivateExtern=*/false, /*includeInSymtab=*/true,
- /*isReferencedDynamically=*/false, /*noDeadStrip=*/false,
- /*isWeakDefCanBeHidden=*/false);
-
- ptrListSym->used = true;
- parentSym->getObjectFile()->symbols.push_back(ptrListSym);
-
- createSymbolReference(parentSym, ptrListSym, linkAtOffset,
- infoCategoryWriter.catBodyInfo.relocTemplate);
-
- uint32_t offset = protocolListHeaderLayout.totalSize;
- for (Symbol *symbol : ptrList.allPtrs) {
- createSymbolReference(ptrListSym, symbol, offset,
- infoCategoryWriter.catPtrListInfo.relocTemplate);
- offset += target->wordSize;
- }
-}
-
-// Generate a pointer list (including header) and link it into the parent at the
-// specified offset. This is used for instance and class methods and
-// proprieties.
-void ObjcCategoryMerger::emitAndLinkPointerList(
- Defined *parentSym, uint32_t linkAtOffset,
- const ClassExtensionInfo &extInfo, const PointerListInfo &ptrList) {
- if (ptrList.allPtrs.empty())
- return;
-
- assert(ptrList.allPtrs.size() * target->wordSize ==
- ptrList.structCount * ptrList.structSize);
-
- // Generate body
- uint32_t bodySize =
- listHeaderLayout.totalSize + (ptrList.structSize * ptrList.structCount);
- llvm::ArrayRef<uint8_t> bodyData = newSectionData(bodySize);
-
- const uint32_t *ptrStructSize = reinterpret_cast<const uint32_t *>(
- bodyData.data() + listHeaderLayout.structSizeOffset);
- const uint32_t *ptrStructCount = reinterpret_cast<const uint32_t *>(
- bodyData.data() + listHeaderLayout.structCountOffset);
-
- *const_cast<uint32_t *>(ptrStructSize) = ptrList.structSize;
- *const_cast<uint32_t *>(ptrStructCount) = ptrList.structCount;
-
- ConcatInputSection *listSec = make<ConcatInputSection>(
- *infoCategoryWriter.catPtrListInfo.inputSection, bodyData,
- infoCategoryWriter.catPtrListInfo.align);
- listSec->parent = infoCategoryWriter.catPtrListInfo.outputSection;
- listSec->live = true;
- allInputSections.push_back(listSec);
-
- listSec->parent = infoCategoryWriter.catPtrListInfo.outputSection;
-
- std::string symName = ptrList.categoryPrefix;
- symName += extInfo.baseClassName + "_$_" + extInfo.mergedContainerName;
-
- Defined *ptrListSym = make<Defined>(
- newStringData(symName.c_str()), /*file=*/parentSym->getObjectFile(),
- listSec, /*value=*/0, bodyData.size(), /*isWeakDef=*/false,
- /*isExternal=*/false, /*isPrivateExtern=*/false, /*includeInSymtab=*/true,
- /*isReferencedDynamically=*/false, /*noDeadStrip=*/false,
- /*isWeakDefCanBeHidden=*/false);
-
- ptrListSym->used = true;
- parentSym->getObjectFile()->symbols.push_back(ptrListSym);
-
- createSymbolReference(parentSym, ptrListSym, linkAtOffset,
- infoCategoryWriter.catBodyInfo.relocTemplate);
-
- uint32_t offset = listHeaderLayout.totalSize;
- for (Symbol *symbol : ptrList.allPtrs) {
- createSymbolReference(ptrListSym, symbol, offset,
- infoCategoryWriter.catPtrListInfo.relocTemplate);
- offset += target->wordSize;
- }
-}
-
-// This method creates an __objc_catlist ConcatInputSection with a single slot
-Defined *
-ObjcCategoryMerger::emitCatListEntrySec(const std::string &forCateogryName,
- const std::string &forBaseClassName,
- ObjFile *objFile) {
- uint32_t sectionSize = target->wordSize;
- llvm::ArrayRef<uint8_t> bodyData = newSectionData(sectionSize);
-
- ConcatInputSection *newCatList =
- make<ConcatInputSection>(*infoCategoryWriter.catListInfo.inputSection,
- bodyData, infoCategoryWriter.catListInfo.align);
- newCatList->parent = infoCategoryWriter.catListInfo.outputSection;
- newCatList->live = true;
- allInputSections.push_back(newCatList);
-
- newCatList->parent = infoCategoryWriter.catListInfo.outputSection;
-
- std::string catSymName = "<__objc_catlist slot for merged category ";
- catSymName += forBaseClassName + "(" + forCateogryName + ")>";
-
- Defined *catListSym = make<Defined>(
- newStringData(catSymName.c_str()), /*file=*/objFile, newCatList,
- /*value=*/0, bodyData.size(), /*isWeakDef=*/false, /*isExternal=*/false,
- /*isPrivateExtern=*/false, /*includeInSymtab=*/false,
- /*isReferencedDynamically=*/false, /*noDeadStrip=*/false,
- /*isWeakDefCanBeHidden=*/false);
-
- catListSym->used = true;
- objFile->symbols.push_back(catListSym);
- return catListSym;
-}
-
-// Here we generate the main category body and link the name and base class into
-// it. We don't link any other info yet like the protocol and class/instance
-// methods/props.
-Defined *ObjcCategoryMerger::emitCategoryBody(const std::string &name,
- const Defined *nameSym,
- const Symbol *baseClassSym,
- const std::string &baseClassName,
- ObjFile *objFile) {
- llvm::ArrayRef<uint8_t> bodyData = newSectionData(catLayout.totalSize);
-
- uint32_t *ptrSize = (uint32_t *)(const_cast<uint8_t *>(bodyData.data()) +
- catLayout.sizeOffset);
- *ptrSize = catLayout.totalSize;
-
- ConcatInputSection *newBodySec =
- make<ConcatInputSection>(*infoCategoryWriter.catBodyInfo.inputSection,
- bodyData, infoCategoryWriter.catBodyInfo.align);
- newBodySec->parent = infoCategoryWriter.catBodyInfo.outputSection;
- newBodySec->live = true;
- allInputSections.push_back(newBodySec);
-
- std::string symName =
- objc::symbol_names::category + baseClassName + "_$_(" + name + ")";
- Defined *catBodySym = make<Defined>(
- newStringData(symName.c_str()), /*file=*/objFile, newBodySec,
- /*value=*/0, bodyData.size(), /*isWeakDef=*/false, /*isExternal=*/false,
- /*isPrivateExtern=*/false, /*includeInSymtab=*/true,
- /*isReferencedDynamically=*/false, /*noDeadStrip=*/false,
- /*isWeakDefCanBeHidden=*/false);
-
- catBodySym->used = true;
- objFile->symbols.push_back(catBodySym);
-
- createSymbolReference(catBodySym, nameSym, catLayout.nameOffset,
- infoCategoryWriter.catBodyInfo.relocTemplate);
-
- // Create a reloc to the base class (either external or internal)
- createSymbolReference(catBodySym, baseClassSym, catLayout.klassOffset,
- infoCategoryWriter.catBodyInfo.relocTemplate);
-
- return catBodySym;
-}
-
-// This writes the new category name (for the merged category) into the binary
-// and returns the sybmol for it.
-Defined *ObjcCategoryMerger::emitCategoryName(const std::string &name,
- ObjFile *objFile) {
- StringRef nameStrData = newStringData(name.c_str());
- // We use +1 below to include the null terminator
- llvm::ArrayRef<uint8_t> nameData(
- reinterpret_cast<const uint8_t *>(nameStrData.data()),
- nameStrData.size() + 1);
-
- auto *parentSection = infoCategoryWriter.catNameInfo.inputSection;
- CStringInputSection *newStringSec = make<CStringInputSection>(
- *infoCategoryWriter.catNameInfo.inputSection, nameData,
- infoCategoryWriter.catNameInfo.align, /*dedupLiterals=*/true);
-
- parentSection->subsections.push_back({0, newStringSec});
-
- newStringSec->splitIntoPieces();
- newStringSec->pieces[0].live = true;
- newStringSec->parent = infoCategoryWriter.catNameInfo.outputSection;
- in.cStringSection->addInput(newStringSec);
- assert(newStringSec->pieces.size() == 1);
-
- Defined *catNameSym = make<Defined>(
- "<merged category name>", /*file=*/objFile, newStringSec,
- /*value=*/0, nameData.size(),
- /*isWeakDef=*/false, /*isExternal=*/false, /*isPrivateExtern=*/false,
- /*includeInSymtab=*/false, /*isReferencedDynamically=*/false,
- /*noDeadStrip=*/false, /*isWeakDefCanBeHidden=*/false);
-
- catNameSym->used = true;
- objFile->symbols.push_back(catNameSym);
- return catNameSym;
-}
-
-// This method fully creates a new category from the given ClassExtensionInfo.
-// It creates the category name, body and method/protocol/prop lists and links
-// them all together. Then it creates a new __objc_catlist entry and adds the
-// category to it. Calling this method will fully generate a category which will
-// be available in the final binary.
-Defined *ObjcCategoryMerger::emitCategory(const ClassExtensionInfo &extInfo) {
- Defined *catNameSym = emitCategoryName(extInfo.mergedContainerName,
- extInfo.objFileForMergeData);
-
- Defined *catBodySym = emitCategoryBody(
- extInfo.mergedContainerName, catNameSym, extInfo.baseClass,
- extInfo.baseClassName, extInfo.objFileForMergeData);
-
- Defined *catListSym =
- emitCatListEntrySec(extInfo.mergedContainerName, extInfo.baseClassName,
- extInfo.objFileForMergeData);
-
- // Add the single category body to the category list at the offset 0.
- createSymbolReference(catListSym, catBodySym, /*offset=*/0,
- infoCategoryWriter.catListInfo.relocTemplate);
-
- emitAndLinkPointerList(catBodySym, catLayout.instanceMethodsOffset, extInfo,
- extInfo.instanceMethods);
-
- emitAndLinkPointerList(catBodySym, catLayout.classMethodsOffset, extInfo,
- extInfo.classMethods);
-
- emitAndLinkProtocolList(catBodySym, catLayout.protocolsOffset, extInfo,
- extInfo.protocols);
-
- emitAndLinkPointerList(catBodySym, catLayout.instancePropsOffset, extInfo,
- extInfo.instanceProps);
-
- emitAndLinkPointerList(catBodySym, catLayout.classPropsOffset, extInfo,
- extInfo.classProps);
-
- return catBodySym;
-}
-
-// This method merges all the categories (sharing a base class) into a single
-// category.
-void ObjcCategoryMerger::mergeCategoriesIntoSingleCategory(
- std::vector<InfoInputCategory> &categories) {
- assert(categories.size() > 1 && "Expected at least 2 categories");
-
- ClassExtensionInfo extInfo(catLayout);
-
- for (auto &catInfo : categories)
- parseCatInfoToExtInfo(catInfo, extInfo);
-
- Defined *newCatDef = emitCategory(extInfo);
- assert(newCatDef && "Failed to create a new category");
-
- for (auto &catInfo : categories)
- catInfo.wasMerged = true;
-}
-
-void ObjcCategoryMerger::createSymbolReference(Defined *refFrom,
- const Symbol *refTo,
- uint32_t offset,
- const Reloc &relocTemplate) {
- Reloc r = relocTemplate;
- r.offset = offset;
- r.addend = 0;
- r.referent = const_cast<Symbol *>(refTo);
- refFrom->isec->relocs.push_back(r);
-}
-
-void ObjcCategoryMerger::collectAndValidateCategoriesData() {
- for (InputSection *sec : allInputSections) {
- if (sec->getName() != section_names::objcCatList)
- continue;
- ConcatInputSection *catListCisec = dyn_cast<ConcatInputSection>(sec);
- assert(catListCisec &&
- "__objc_catList InputSection is not a ConcatInputSection");
-
- for (uint32_t off = 0; off < catListCisec->getSize();
- off += target->wordSize) {
- Defined *categorySym = tryGetDefinedAtIsecOffset(catListCisec, off);
- assert(categorySym &&
- "Failed to get a valid cateogry at __objc_catlit offset");
-
- // We only support ObjC categories (no swift + @objc)
- // TODO: Support swift + @objc categories also
- if (!categorySym->getName().starts_with(objc::symbol_names::category))
- continue;
-
- auto *catBodyIsec = dyn_cast<ConcatInputSection>(categorySym->isec);
- assert(catBodyIsec &&
- "Category data section is not an ConcatInputSection");
-
- // Check that the category has a reloc at 'klassOffset' (which is
- // a pointer to the class symbol)
-
- Symbol *classSym =
- tryGetSymbolAtIsecOffset(catBodyIsec, catLayout.klassOffset);
- assert(classSym && "Category does not have a valid base class");
-
- InfoInputCategory catInputInfo{catListCisec, catBodyIsec, off};
- categoryMap[classSym].push_back(catInputInfo);
-
- collectCategoryWriterInfoFromCategory(catInputInfo);
- }
- }
-}
-
-// In the input we have multiple __objc_catlist InputSection, each of which may
-// contain links to multiple categories. Of these categories, we will merge (and
-// erase) only some. There will be some categories that will remain untouched
-// (not erased). For these not erased categories, we generate new __objc_catlist
-// entries since the parent __objc_catlist entry will be erased
-void ObjcCategoryMerger::generateCatListForNonErasedCategories(
- const std::map<ConcatInputSection *, std::set<uint64_t>>
- catListToErasedOffsets) {
-
- // Go through all offsets of all __objc_catlist's that we process and if there
- // are categories that we didn't process - generate a new __objc_catlist for
- // each.
- for (auto &mapEntry : catListToErasedOffsets) {
- ConcatInputSection *catListIsec = mapEntry.first;
- for (uint32_t catListIsecOffset = 0;
- catListIsecOffset < catListIsec->data.size();
- catListIsecOffset += target->wordSize) {
- // This slot was erased, we can just skip it
- if (mapEntry.second.count(catListIsecOffset))
- continue;
-
- Defined *nonErasedCatBody =
- tryGetDefinedAtIsecOffset(catListIsec, catListIsecOffset);
- assert(nonErasedCatBody && "Failed to relocate non-deleted category");
-
- // Allocate data for the new __objc_catlist slot
- auto bodyData = newSectionData(target->wordSize);
-
- // We mark the __objc_catlist slot as belonging to the same file as the
- // category
- ObjFile *objFile = dyn_cast<ObjFile>(nonErasedCatBody->getFile());
-
- ConcatInputSection *listSec = make<ConcatInputSection>(
- *infoCategoryWriter.catListInfo.inputSection, bodyData,
- infoCategoryWriter.catListInfo.align);
- listSec->parent = infoCategoryWriter.catListInfo.outputSection;
- listSec->live = true;
- allInputSections.push_back(listSec);
-
- std::string slotSymName = "<__objc_catlist slot for category ";
- slotSymName += nonErasedCatBody->getName();
- slotSymName += ">";
-
- Defined *catListSlotSym = make<Defined>(
- newStringData(slotSymName.c_str()), /*file=*/objFile, listSec,
- /*value=*/0, bodyData.size(),
- /*isWeakDef=*/false, /*isExternal=*/false, /*isPrivateExtern=*/false,
- /*includeInSymtab=*/false, /*isReferencedDynamically=*/false,
- /*noDeadStrip=*/false, /*isWeakDefCanBeHidden=*/false);
-
- catListSlotSym->used = true;
- objFile->symbols.push_back(catListSlotSym);
-
- // Now link the category body into the newly created slot
- createSymbolReference(catListSlotSym, nonErasedCatBody, 0,
- infoCategoryWriter.catListInfo.relocTemplate);
- }
- }
-}
-
-void ObjcCategoryMerger::eraseISec(ConcatInputSection *isec) {
- isec->live = false;
- for (auto &sym : isec->symbols)
- sym->used = false;
-}
-
-// This fully erases the merged categories, including their body, their names,
-// their method/protocol/prop lists and the __objc_catlist entries that link to
-// them.
-void ObjcCategoryMerger::eraseMergedCategories() {
- // Map of InputSection to a set of offsets of the categories that were merged
- std::map<ConcatInputSection *, std::set<uint64_t>> catListToErasedOffsets;
-
- for (auto &mapEntry : categoryMap) {
- for (InfoInputCategory &catInfo : mapEntry.second) {
- if (catInfo.wasMerged) {
- eraseISec(catInfo.catListIsec);
- catListToErasedOffsets[catInfo.catListIsec].insert(
- catInfo.offCatListIsec);
- }
- }
- }
-
- // If there were categories that we did not erase, we need to generate a new
- // __objc_catList that contains only the un-merged categories, and get rid of
- // the references to the ones we merged.
- generateCatListForNonErasedCategories(catListToErasedOffsets);
-
- // Erase the old method lists & names of the categories that were merged
- for (auto &mapEntry : categoryMap) {
- for (InfoInputCategory &catInfo : mapEntry.second) {
- if (!catInfo.wasMerged)
- continue;
-
- eraseISec(catInfo.catBodyIsec);
- tryEraseDefinedAtIsecOffset(catInfo.catBodyIsec, catLayout.nameOffset);
- tryEraseDefinedAtIsecOffset(catInfo.catBodyIsec,
- catLayout.instanceMethodsOffset);
- tryEraseDefinedAtIsecOffset(catInfo.catBodyIsec,
- catLayout.classMethodsOffset);
- tryEraseDefinedAtIsecOffset(catInfo.catBodyIsec,
- catLayout.protocolsOffset);
- tryEraseDefinedAtIsecOffset(catInfo.catBodyIsec,
- catLayout.classPropsOffset);
- tryEraseDefinedAtIsecOffset(catInfo.catBodyIsec,
- catLayout.instancePropsOffset);
- }
- }
-}
-
-void ObjcCategoryMerger::doMerge() {
- collectAndValidateCategoriesData();
-
- for (auto &entry : categoryMap)
- if (entry.second.size() > 1)
- // Merge all categories into a new, single category
- mergeCategoriesIntoSingleCategory(entry.second);
-
- // Erase all categories that were merged
- eraseMergedCategories();
-}
-
-void ObjcCategoryMerger::doCleanup() { generatedSectionData.clear(); }
-
-StringRef ObjcCategoryMerger::newStringData(const char *str) {
- uint32_t len = strlen(str);
- auto &data = newSectionData(len + 1);
- char *strData = reinterpret_cast<char *>(data.data());
- strncpy(strData, str, len);
- return StringRef(strData, len);
-}
-
-SmallVector<uint8_t> &ObjcCategoryMerger::newSectionData(uint32_t size) {
- generatedSectionData.push_back(SmallVector<uint8_t>(size, 0));
- return generatedSectionData.back();
-}
-
-} // namespace
-
-void objc::mergeCategories() {
- TimeTraceScope timeScope("ObjcCategoryMerger");
-
- ObjcCategoryMerger merger(inputSections);
- merger.doMerge();
-}
-
-void objc::doCleanup() { ObjcCategoryMerger::doCleanup(); }
diff --git a/lld/MachO/ObjC.h b/lld/MachO/ObjC.h
index 9fbe984e6223ec..4c65f9a1f78812 100644
--- a/lld/MachO/ObjC.h
+++ b/lld/MachO/ObjC.h
@@ -17,26 +17,14 @@ namespace objc {
namespace symbol_names {
constexpr const char klass[] = "_OBJC_CLASS_$_";
-constexpr const char klassPropList[] = "__OBJC_$_CLASS_PROP_LIST_";
-
constexpr const char metaclass[] = "_OBJC_METACLASS_$_";
constexpr const char ehtype[] = "_OBJC_EHTYPE_$_";
constexpr const char ivar[] = "_OBJC_IVAR_$_";
-constexpr const char listProprieties[] = "__OBJC_$_PROP_LIST_";
-
-constexpr const char category[] = "__OBJC_$_CATEGORY_";
-constexpr const char categoryInstanceMethods[] =
- "__OBJC_$_CATEGORY_INSTANCE_METHODS_";
-constexpr const char categoryClassMethods[] =
- "__OBJC_$_CATEGORY_CLASS_METHODS_";
-constexpr const char categoryProtocols[] = "__OBJC_CATEGORY_PROTOCOLS_$_";
} // namespace symbol_names
// Check for duplicate method names within related categories / classes.
void checkCategories();
-void mergeCategories();
-void doCleanup();
} // namespace objc
bool hasObjCSection(llvm::MemoryBufferRef);
diff --git a/lld/MachO/Options.td b/lld/MachO/Options.td
index 0d8ee2a0926be2..a524e4a4c50841 100644
--- a/lld/MachO/Options.td
+++ b/lld/MachO/Options.td
@@ -129,12 +129,6 @@ def strict_auto_link : Flag<["--"], "strict-auto-link">,
def check_category_conflicts : Flag<["--"], "check-category-conflicts">,
HelpText<"Check for conflicts between category & class methods">,
Group<grp_lld>;
-def objc_category_merging : Flag<["-"], "objc_category_merging">,
- HelpText<"Merge Objective-C categories that share the same base class">,
- Group<grp_lld>;
-def no_objc_category_merging : Flag<["-"], "no_objc_category_merging">,
- HelpText<"Do not merge Objective-C categories">,
- Group<grp_lld>;
def lto_debug_pass_manager: Flag<["--"], "lto-debug-pass-manager">,
HelpText<"Debug new pass manager">, Group<grp_lld>;
def cs_profile_generate: Flag<["--"], "cs-profile-generate">,
@@ -972,6 +966,10 @@ def interposable_list : Separate<["-"], "interposable_list">,
def no_function_starts : Flag<["-"], "no_function_starts">,
HelpText<"Do not create table of function start addresses">,
Group<grp_rare>;
+def no_objc_category_merging : Flag<["-"], "no_objc_category_merging">,
+ HelpText<"Do not merge Objective-C categories into their classes">,
+ Flags<[HelpHidden]>,
+ Group<grp_rare>;
def object_path_lto : Separate<["-"], "object_path_lto">,
MetaVarName<"<path>">,
HelpText<"Retain any temporary mach-o file in <path> that would otherwise be deleted during LTO">,
diff --git a/lld/test/MachO/objc-category-merging-complete-test.s b/lld/test/MachO/objc-category-merging-complete-test.s
deleted file mode 100644
index 3bc3ca26b6ae6c..00000000000000
--- a/lld/test/MachO/objc-category-merging-complete-test.s
+++ /dev/null
@@ -1,762 +0,0 @@
-# REQUIRES: aarch64
-# RUN: rm -rf %t; split-file %s %t && cd %t
-
-## Create a dylib to link against(a64_file1.dylib) and merge categories in the main binary (file2_merge_a64.exe)
-# RUN: llvm-mc -filetype=obj -triple=arm64-apple-macos -o a64_file1.o a64_file1.s
-# RUN: %lld -arch arm64 a64_file1.o -o a64_file1.dylib -dylib
-
-# RUN: llvm-mc -filetype=obj -triple=arm64-apple-macos -o a64_file2.o a64_file2.s
-# RUN: %lld -arch arm64 -o a64_file2_no_merge.exe a64_file1.dylib a64_file2.o
-# RUN: %lld -arch arm64 -o a64_file2_merge.exe -objc_category_merging a64_file1.dylib a64_file2.o
-
-# RUN: llvm-objdump --objc-meta-data --macho a64_file2_no_merge.exe | FileCheck %s --check-prefixes=NO_MERGE_CATS
-# RUN: llvm-objdump --objc-meta-data --macho a64_file2_merge.exe | FileCheck %s --check-prefixes=MERGE_CATS
-
-
-MERGE_CATS: __OBJC_$_CATEGORY_MyBaseClass_$_(Category02|Category03)
-MERGE_CATS-NEXT: name {{.*}} Category02|Category03
-MERGE_CATS: instanceMethods
-MERGE_CATS-NEXT: entsize 24
-MERGE_CATS-NEXT: count 4
-MERGE_CATS-NEXT: name {{.*}} class02InstanceMethod
-MERGE_CATS-NEXT: types {{.*}} v16 at 0:8
-MERGE_CATS-NEXT: imp -[MyBaseClass(Category02) class02InstanceMethod]
-MERGE_CATS-NEXT: name {{.*}} myProtocol02Method
-MERGE_CATS-NEXT: types {{.*}} v16 at 0:8
-MERGE_CATS-NEXT: imp -[MyBaseClass(Category02) myProtocol02Method]
-MERGE_CATS-NEXT: name {{.*}} class03InstanceMethod
-MERGE_CATS-NEXT: types {{.*}} v16 at 0:8
-MERGE_CATS-NEXT: imp -[MyBaseClass(Category03) class03InstanceMethod]
-MERGE_CATS-NEXT: name {{.*}} myProtocol03Method
-MERGE_CATS-NEXT: types {{.*}} v16 at 0:8
-MERGE_CATS-NEXT: imp -[MyBaseClass(Category03) myProtocol03Method]
-MERGE_CATS-NEXT: classMethods {{.*}}
-MERGE_CATS-NEXT: entsize 24
-MERGE_CATS-NEXT: count 4
-MERGE_CATS-NEXT: name {{.*}} class02ClassMethod
-MERGE_CATS-NEXT: types {{.*}} v16 at 0:8
-MERGE_CATS-NEXT: imp +[MyBaseClass(Category02) class02ClassMethod]
-MERGE_CATS-NEXT: name {{.*}} MyProtocol02Prop
-MERGE_CATS-NEXT: types {{.*}} i16 at 0:8
-MERGE_CATS-NEXT: imp +[MyBaseClass(Category02) MyProtocol02Prop]
-MERGE_CATS-NEXT: name {{.*}} class03ClassMethod
-MERGE_CATS-NEXT: types {{.*}} v16 at 0:8
-MERGE_CATS-NEXT: imp +[MyBaseClass(Category03) class03ClassMethod]
-MERGE_CATS-NEXT: name {{.*}} MyProtocol03Prop
-MERGE_CATS-NEXT: types {{.*}} i16 at 0:8
-MERGE_CATS-NEXT: imp +[MyBaseClass(Category03) MyProtocol03Prop]
-MERGE_CATS-NEXT: protocols
-MERGE_CATS-NEXT: count 2
-MERGE_CATS-NEXT: list[0] {{.*}} (struct protocol_t *)
-MERGE_CATS-NEXT: isa 0x0
-MERGE_CATS-NEXT: name {{.*}} MyProtocol02
-MERGE_CATS-NEXT: protocols 0x0
-MERGE_CATS-NEXT: instanceMethods
-MERGE_CATS-NEXT: entsize 24
-MERGE_CATS-NEXT: count 2
-MERGE_CATS-NEXT: name {{.*}} myProtocol02Method
-MERGE_CATS-NEXT: types {{.*}} v16 at 0:8
-MERGE_CATS-NEXT: imp 0x0
-MERGE_CATS-NEXT: name {{.*}} MyProtocol02Prop
-MERGE_CATS-NEXT: types {{.*}} i16 at 0:8
-MERGE_CATS-NEXT: imp 0x0
-MERGE_CATS-NEXT: classMethods
-MERGE_CATS-NEXT: optionalInstanceMethods 0x0
-MERGE_CATS-NEXT: optionalClassMethods 0x0
-MERGE_CATS-NEXT: instanceProperties {{.*}}
-MERGE_CATS-NEXT: list[1] {{.*}}
-MERGE_CATS-NEXT: isa 0x0
-MERGE_CATS-NEXT: name {{.*}} MyProtocol03
-MERGE_CATS-NEXT: protocols 0x0
-MERGE_CATS-NEXT: instanceMethods
-MERGE_CATS-NEXT: entsize 24
-MERGE_CATS-NEXT: count 2
-MERGE_CATS-NEXT: name {{.*}} myProtocol03Method
-MERGE_CATS-NEXT: types {{.*}} v16 at 0:8
-MERGE_CATS-NEXT: imp 0x0
-MERGE_CATS-NEXT: name {{.*}} MyProtocol03Prop
-MERGE_CATS-NEXT: types {{.*}} i16 at 0:8
-MERGE_CATS-NEXT: imp 0x0
-MERGE_CATS-NEXT: classMethods 0x0
-MERGE_CATS-NEXT: optionalInstanceMethods 0x0
-MERGE_CATS-NEXT: optionalClassMethods 0x0
-MERGE_CATS-NEXT: instanceProperties {{.*}}
-MERGE_CATS-NEXT: instanceProperties
-MERGE_CATS-NEXT: entsize 16
-MERGE_CATS-NEXT: count 2
-MERGE_CATS-NEXT: name {{.*}} MyProtocol02Prop
-MERGE_CATS-NEXT: attributes {{.*}} Ti,R,D
-MERGE_CATS-NEXT: name {{.*}} MyProtocol03Prop
-MERGE_CATS-NEXT: attributes {{.*}} Ti,R,D
-
-
-NO_MERGE_CATS-NOT: __OBJC_$_CATEGORY_MyBaseClass_$_(Category02|Category03)
-NO_MERGE_CATS: __OBJC_$_CATEGORY_MyBaseClass_$_Category02
-NO_MERGE_CATS: instanceMethods
-NO_MERGE_CATS-NEXT: 24
-NO_MERGE_CATS-NEXT: 2
-NO_MERGE_CATS: classMethods
-NO_MERGE_CATS-NEXT: 24
-NO_MERGE_CATS-NEXT: 2
-
-
-#--- a64_file1.s
-
-## @protocol MyProtocol01
-## - (void)myProtocol01Method;
-## @property (nonatomic) int MyProtocol01Prop;
-## @end
-##
-## __attribute__((objc_root_class))
-## @interface MyBaseClass<MyProtocol01>
-## - (void)baseInstanceMethod;
-## - (void)myProtocol01Method;
-## + (void)baseClassMethod;
-## @end
-##
-## @implementation MyBaseClass
-## @synthesize MyProtocol01Prop;
-## - (void)baseInstanceMethod {}
-## - (void)myProtocol01Method {}
-## + (void)baseClassMethod {}
-## @end
-##
-## void *_objc_empty_cache;
-
- .section __TEXT,__text,regular,pure_instructions
- .p2align 2 ; -- Begin function -[MyBaseClass baseInstanceMethod]
-"-[MyBaseClass baseInstanceMethod]": ; @"\01-[MyBaseClass baseInstanceMethod]"
- .cfi_startproc
-; %bb.0: ; %entry
- ret
- .cfi_endproc
- ; -- End function
- .p2align 2 ; -- Begin function -[MyBaseClass myProtocol01Method]
-"-[MyBaseClass myProtocol01Method]": ; @"\01-[MyBaseClass myProtocol01Method]"
- .cfi_startproc
-; %bb.0: ; %entry
- ret
- .cfi_endproc
- ; -- End function
- .p2align 2 ; -- Begin function +[MyBaseClass baseClassMethod]
-"+[MyBaseClass baseClassMethod]": ; @"\01+[MyBaseClass baseClassMethod]"
- .cfi_startproc
-; %bb.0: ; %entry
- ret
- .cfi_endproc
- ; -- End function
- .p2align 2 ; -- Begin function -[MyBaseClass MyProtocol01Prop]
-"-[MyBaseClass MyProtocol01Prop]": ; @"\01-[MyBaseClass MyProtocol01Prop]"
- .cfi_startproc
-; %bb.0: ; %entry
-Lloh0:
- adrp x8, _OBJC_IVAR_$_MyBaseClass.MyProtocol01Prop at PAGE
-Lloh1:
- ldrsw x8, [x8, _OBJC_IVAR_$_MyBaseClass.MyProtocol01Prop at PAGEOFF]
- ldr w0, [x0, x8]
- ret
- .loh AdrpLdr Lloh0, Lloh1
- .cfi_endproc
- ; -- End function
- .p2align 2 ; -- Begin function -[MyBaseClass setMyProtocol01Prop:]
-"-[MyBaseClass setMyProtocol01Prop:]": ; @"\01-[MyBaseClass setMyProtocol01Prop:]"
- .cfi_startproc
-; %bb.0: ; %entry
-Lloh2:
- adrp x8, _OBJC_IVAR_$_MyBaseClass.MyProtocol01Prop at PAGE
-Lloh3:
- ldrsw x8, [x8, _OBJC_IVAR_$_MyBaseClass.MyProtocol01Prop at PAGEOFF]
- str w2, [x0, x8]
- ret
- .loh AdrpLdr Lloh2, Lloh3
- .cfi_endproc
- ; -- End function
- .private_extern _OBJC_IVAR_$_MyBaseClass.MyProtocol01Prop ; @"OBJC_IVAR_$_MyBaseClass.MyProtocol01Prop"
- .section __DATA,__objc_ivar
- .globl _OBJC_IVAR_$_MyBaseClass.MyProtocol01Prop
- .p2align 2, 0x0
-_OBJC_IVAR_$_MyBaseClass.MyProtocol01Prop:
- .long 0 ; 0x0
- .section __DATA,__objc_data
- .globl _OBJC_CLASS_$_MyBaseClass ; @"OBJC_CLASS_$_MyBaseClass"
- .p2align 3, 0x0
-_OBJC_CLASS_$_MyBaseClass:
- .quad _OBJC_METACLASS_$_MyBaseClass
- .quad 0
- .quad __objc_empty_cache
- .quad 0
- .quad __OBJC_CLASS_RO_$_MyBaseClass
- .globl _OBJC_METACLASS_$_MyBaseClass ; @"OBJC_METACLASS_$_MyBaseClass"
- .p2align 3, 0x0
-_OBJC_METACLASS_$_MyBaseClass:
- .quad _OBJC_METACLASS_$_MyBaseClass
- .quad _OBJC_CLASS_$_MyBaseClass
- .quad __objc_empty_cache
- .quad 0
- .quad __OBJC_METACLASS_RO_$_MyBaseClass
- .section __TEXT,__objc_classname,cstring_literals
-l_OBJC_CLASS_NAME_: ; @OBJC_CLASS_NAME_
- .asciz "MyBaseClass"
- .section __TEXT,__objc_methname,cstring_literals
-l_OBJC_METH_VAR_NAME_: ; @OBJC_METH_VAR_NAME_
- .asciz "baseClassMethod"
- .section __TEXT,__objc_methtype,cstring_literals
-l_OBJC_METH_VAR_TYPE_: ; @OBJC_METH_VAR_TYPE_
- .asciz "v16 at 0:8"
- .section __DATA,__objc_const
- .p2align 3, 0x0 ; @"_OBJC_$_CLASS_METHODS_MyBaseClass"
-__OBJC_$_CLASS_METHODS_MyBaseClass:
- .long 24 ; 0x18
- .long 1 ; 0x1
- .quad l_OBJC_METH_VAR_NAME_
- .quad l_OBJC_METH_VAR_TYPE_
- .quad "+[MyBaseClass baseClassMethod]"
- .section __TEXT,__objc_classname,cstring_literals
-l_OBJC_CLASS_NAME_.1: ; @OBJC_CLASS_NAME_.1
- .asciz "MyProtocol01"
- .section __TEXT,__objc_methname,cstring_literals
-l_OBJC_METH_VAR_NAME_.2: ; @OBJC_METH_VAR_NAME_.2
- .asciz "myProtocol01Method"
-l_OBJC_METH_VAR_NAME_.3: ; @OBJC_METH_VAR_NAME_.3
- .asciz "MyProtocol01Prop"
- .section __TEXT,__objc_methtype,cstring_literals
-l_OBJC_METH_VAR_TYPE_.4: ; @OBJC_METH_VAR_TYPE_.4
- .asciz "i16 at 0:8"
- .section __TEXT,__objc_methname,cstring_literals
-l_OBJC_METH_VAR_NAME_.5: ; @OBJC_METH_VAR_NAME_.5
- .asciz "setMyProtocol01Prop:"
- .section __TEXT,__objc_methtype,cstring_literals
-l_OBJC_METH_VAR_TYPE_.6: ; @OBJC_METH_VAR_TYPE_.6
- .asciz "v20 at 0:8i16"
- .section __DATA,__objc_const
- .p2align 3, 0x0 ; @"_OBJC_$_PROTOCOL_INSTANCE_METHODS_MyProtocol01"
-__OBJC_$_PROTOCOL_INSTANCE_METHODS_MyProtocol01:
- .long 24 ; 0x18
- .long 3 ; 0x3
- .quad l_OBJC_METH_VAR_NAME_.2
- .quad l_OBJC_METH_VAR_TYPE_
- .quad 0
- .quad l_OBJC_METH_VAR_NAME_.3
- .quad l_OBJC_METH_VAR_TYPE_.4
- .quad 0
- .quad l_OBJC_METH_VAR_NAME_.5
- .quad l_OBJC_METH_VAR_TYPE_.6
- .quad 0
- .section __TEXT,__objc_methname,cstring_literals
-l_OBJC_PROP_NAME_ATTR_: ; @OBJC_PROP_NAME_ATTR_
- .asciz "MyProtocol01Prop"
-l_OBJC_PROP_NAME_ATTR_.7: ; @OBJC_PROP_NAME_ATTR_.7
- .asciz "Ti,N"
- .section __DATA,__objc_const
- .p2align 3, 0x0 ; @"_OBJC_$_PROP_LIST_MyProtocol01"
-__OBJC_$_PROP_LIST_MyProtocol01:
- .long 16 ; 0x10
- .long 1 ; 0x1
- .quad l_OBJC_PROP_NAME_ATTR_
- .quad l_OBJC_PROP_NAME_ATTR_.7
- .p2align 3, 0x0 ; @"_OBJC_$_PROTOCOL_METHOD_TYPES_MyProtocol01"
-__OBJC_$_PROTOCOL_METHOD_TYPES_MyProtocol01:
- .quad l_OBJC_METH_VAR_TYPE_
- .quad l_OBJC_METH_VAR_TYPE_.4
- .quad l_OBJC_METH_VAR_TYPE_.6
- .private_extern __OBJC_PROTOCOL_$_MyProtocol01 ; @"_OBJC_PROTOCOL_$_MyProtocol01"
- .section __DATA,__data
- .globl __OBJC_PROTOCOL_$_MyProtocol01
- .weak_definition __OBJC_PROTOCOL_$_MyProtocol01
- .p2align 3, 0x0
-__OBJC_PROTOCOL_$_MyProtocol01:
- .quad 0
- .quad l_OBJC_CLASS_NAME_.1
- .quad 0
- .quad __OBJC_$_PROTOCOL_INSTANCE_METHODS_MyProtocol01
- .quad 0
- .quad 0
- .quad 0
- .quad __OBJC_$_PROP_LIST_MyProtocol01
- .long 96 ; 0x60
- .long 0 ; 0x0
- .quad __OBJC_$_PROTOCOL_METHOD_TYPES_MyProtocol01
- .quad 0
- .quad 0
- .private_extern __OBJC_LABEL_PROTOCOL_$_MyProtocol01 ; @"_OBJC_LABEL_PROTOCOL_$_MyProtocol01"
- .section __DATA,__objc_protolist,coalesced,no_dead_strip
- .globl __OBJC_LABEL_PROTOCOL_$_MyProtocol01
- .weak_definition __OBJC_LABEL_PROTOCOL_$_MyProtocol01
- .p2align 3, 0x0
-__OBJC_LABEL_PROTOCOL_$_MyProtocol01:
- .quad __OBJC_PROTOCOL_$_MyProtocol01
- .section __DATA,__objc_const
- .p2align 3, 0x0 ; @"_OBJC_CLASS_PROTOCOLS_$_MyBaseClass"
-__OBJC_CLASS_PROTOCOLS_$_MyBaseClass:
- .quad 1 ; 0x1
- .quad __OBJC_PROTOCOL_$_MyProtocol01
- .quad 0
- .p2align 3, 0x0 ; @"_OBJC_METACLASS_RO_$_MyBaseClass"
-__OBJC_METACLASS_RO_$_MyBaseClass:
- .long 3 ; 0x3
- .long 40 ; 0x28
- .long 40 ; 0x28
- .space 4
- .quad 0
- .quad l_OBJC_CLASS_NAME_
- .quad __OBJC_$_CLASS_METHODS_MyBaseClass
- .quad __OBJC_CLASS_PROTOCOLS_$_MyBaseClass
- .quad 0
- .quad 0
- .quad 0
- .section __TEXT,__objc_methname,cstring_literals
-l_OBJC_METH_VAR_NAME_.8: ; @OBJC_METH_VAR_NAME_.8
- .asciz "baseInstanceMethod"
- .section __DATA,__objc_const
- .p2align 3, 0x0 ; @"_OBJC_$_INSTANCE_METHODS_MyBaseClass"
-__OBJC_$_INSTANCE_METHODS_MyBaseClass:
- .long 24 ; 0x18
- .long 4 ; 0x4
- .quad l_OBJC_METH_VAR_NAME_.8
- .quad l_OBJC_METH_VAR_TYPE_
- .quad "-[MyBaseClass baseInstanceMethod]"
- .quad l_OBJC_METH_VAR_NAME_.2
- .quad l_OBJC_METH_VAR_TYPE_
- .quad "-[MyBaseClass myProtocol01Method]"
- .quad l_OBJC_METH_VAR_NAME_.3
- .quad l_OBJC_METH_VAR_TYPE_.4
- .quad "-[MyBaseClass MyProtocol01Prop]"
- .quad l_OBJC_METH_VAR_NAME_.5
- .quad l_OBJC_METH_VAR_TYPE_.6
- .quad "-[MyBaseClass setMyProtocol01Prop:]"
- .section __TEXT,__objc_methtype,cstring_literals
-l_OBJC_METH_VAR_TYPE_.9: ; @OBJC_METH_VAR_TYPE_.9
- .asciz "i"
- .section __DATA,__objc_const
- .p2align 3, 0x0 ; @"_OBJC_$_INSTANCE_VARIABLES_MyBaseClass"
-__OBJC_$_INSTANCE_VARIABLES_MyBaseClass:
- .long 32 ; 0x20
- .long 1 ; 0x1
- .quad _OBJC_IVAR_$_MyBaseClass.MyProtocol01Prop
- .quad l_OBJC_METH_VAR_NAME_.3
- .quad l_OBJC_METH_VAR_TYPE_.9
- .long 2 ; 0x2
- .long 4 ; 0x4
- .section __TEXT,__objc_methname,cstring_literals
-l_OBJC_PROP_NAME_ATTR_.10: ; @OBJC_PROP_NAME_ATTR_.10
- .asciz "Ti,N,VMyProtocol01Prop"
- .section __DATA,__objc_const
- .p2align 3, 0x0 ; @"_OBJC_$_PROP_LIST_MyBaseClass"
-__OBJC_$_PROP_LIST_MyBaseClass:
- .long 16 ; 0x10
- .long 1 ; 0x1
- .quad l_OBJC_PROP_NAME_ATTR_
- .quad l_OBJC_PROP_NAME_ATTR_.10
- .p2align 3, 0x0 ; @"_OBJC_CLASS_RO_$_MyBaseClass"
-__OBJC_CLASS_RO_$_MyBaseClass:
- .long 2 ; 0x2
- .long 0 ; 0x0
- .long 4 ; 0x4
- .space 4
- .quad 0
- .quad l_OBJC_CLASS_NAME_
- .quad __OBJC_$_INSTANCE_METHODS_MyBaseClass
- .quad __OBJC_CLASS_PROTOCOLS_$_MyBaseClass
- .quad __OBJC_$_INSTANCE_VARIABLES_MyBaseClass
- .quad 0
- .quad __OBJC_$_PROP_LIST_MyBaseClass
- .globl __objc_empty_cache ; @_objc_empty_cache
-.zerofill __DATA,__common,__objc_empty_cache,8,3
- .section __DATA,__objc_classlist,regular,no_dead_strip
- .p2align 3, 0x0 ; @"OBJC_LABEL_CLASS_$"
-l_OBJC_LABEL_CLASS_$:
- .quad _OBJC_CLASS_$_MyBaseClass
- .no_dead_strip __OBJC_LABEL_PROTOCOL_$_MyProtocol01
- .no_dead_strip __OBJC_PROTOCOL_$_MyProtocol01
- .section __DATA,__objc_imageinfo,regular,no_dead_strip
-L_OBJC_IMAGE_INFO:
- .long 0
- .long 96
-.subsections_via_symbols
-
-
-#--- a64_file2.s
-
-## @protocol MyProtocol01
-## - (void)myProtocol01Method;
-## @end
-##
-## @protocol MyProtocol02
-## - (void)myProtocol02Method;
-## @property(readonly) int MyProtocol02Prop;
-## @end
-##
-## @protocol MyProtocol03
-## - (void)myProtocol03Method;
-## @property(readonly) int MyProtocol03Prop;
-## @end
-##
-##
-## __attribute__((objc_root_class))
-## @interface MyBaseClass<MyProtocol01>
-## - (void)baseInstanceMethod;
-## - (void)myProtocol01Method;
-## + (void)baseClassMethod;
-## @end
-##
-##
-##
-## @interface MyBaseClass(Category02)<MyProtocol02>
-## - (void)class02InstanceMethod;
-## - (void)myProtocol02Method;
-## + (void)class02ClassMethod;
-## + (int)MyProtocol02Prop;
-## @end
-##
-## @implementation MyBaseClass(Category02)
-## - (void)class02InstanceMethod {}
-## - (void)myProtocol02Method {}
-## + (void)class02ClassMethod {}
-## + (int)MyProtocol02Prop { return 0;}
-## @dynamic MyProtocol02Prop;
-## @end
-##
-## @interface MyBaseClass(Category03)<MyProtocol03>
-## - (void)class03InstanceMethod;
-## - (void)myProtocol03Method;
-## + (void)class03ClassMethod;
-## + (int)MyProtocol03Prop;
-## @end
-##
-## @implementation MyBaseClass(Category03)
-## - (void)class03InstanceMethod {}
-## - (void)myProtocol03Method {}
-## + (void)class03ClassMethod {}
-## + (int)MyProtocol03Prop { return 0;}
-## @dynamic MyProtocol03Prop;
-## @end
-##
-## int main() {
-## return 0;
-## }
-
-
- .section __TEXT,__text,regular,pure_instructions
- .p2align 2 ; -- Begin function -[MyBaseClass(Category02) class02InstanceMethod]
-"-[MyBaseClass(Category02) class02InstanceMethod]": ; @"\01-[MyBaseClass(Category02) class02InstanceMethod]"
- .cfi_startproc
-; %bb.0: ; %entry
- ret
- .cfi_endproc
- ; -- End function
- .p2align 2 ; -- Begin function -[MyBaseClass(Category02) myProtocol02Method]
-"-[MyBaseClass(Category02) myProtocol02Method]": ; @"\01-[MyBaseClass(Category02) myProtocol02Method]"
- .cfi_startproc
-; %bb.0: ; %entry
- ret
- .cfi_endproc
- ; -- End function
- .p2align 2 ; -- Begin function +[MyBaseClass(Category02) class02ClassMethod]
-"+[MyBaseClass(Category02) class02ClassMethod]": ; @"\01+[MyBaseClass(Category02) class02ClassMethod]"
- .cfi_startproc
-; %bb.0: ; %entry
- ret
- .cfi_endproc
- ; -- End function
- .p2align 2 ; -- Begin function +[MyBaseClass(Category02) MyProtocol02Prop]
-"+[MyBaseClass(Category02) MyProtocol02Prop]": ; @"\01+[MyBaseClass(Category02) MyProtocol02Prop]"
- .cfi_startproc
-; %bb.0: ; %entry
- b _OUTLINED_FUNCTION_0
- .cfi_endproc
- ; -- End function
- .p2align 2 ; -- Begin function -[MyBaseClass(Category03) class03InstanceMethod]
-"-[MyBaseClass(Category03) class03InstanceMethod]": ; @"\01-[MyBaseClass(Category03) class03InstanceMethod]"
- .cfi_startproc
-; %bb.0: ; %entry
- ret
- .cfi_endproc
- ; -- End function
- .p2align 2 ; -- Begin function -[MyBaseClass(Category03) myProtocol03Method]
-"-[MyBaseClass(Category03) myProtocol03Method]": ; @"\01-[MyBaseClass(Category03) myProtocol03Method]"
- .cfi_startproc
-; %bb.0: ; %entry
- ret
- .cfi_endproc
- ; -- End function
- .p2align 2 ; -- Begin function +[MyBaseClass(Category03) class03ClassMethod]
-"+[MyBaseClass(Category03) class03ClassMethod]": ; @"\01+[MyBaseClass(Category03) class03ClassMethod]"
- .cfi_startproc
-; %bb.0: ; %entry
- ret
- .cfi_endproc
- ; -- End function
- .p2align 2 ; -- Begin function +[MyBaseClass(Category03) MyProtocol03Prop]
-"+[MyBaseClass(Category03) MyProtocol03Prop]": ; @"\01+[MyBaseClass(Category03) MyProtocol03Prop]"
- .cfi_startproc
-; %bb.0: ; %entry
- b _OUTLINED_FUNCTION_0
- .cfi_endproc
- ; -- End function
- .globl _main ; -- Begin function main
- .p2align 2
-_main: ; @main
- .cfi_startproc
-; %bb.0: ; %entry
- b _OUTLINED_FUNCTION_0
- .cfi_endproc
- ; -- End function
- .p2align 2 ; -- Begin function OUTLINED_FUNCTION_0
-_OUTLINED_FUNCTION_0: ; @OUTLINED_FUNCTION_0 Tail Call
- .cfi_startproc
-; %bb.0:
- mov w0, #0
- ret
- .cfi_endproc
- ; -- End function
- .section __TEXT,__objc_classname,cstring_literals
-l_OBJC_CLASS_NAME_: ; @OBJC_CLASS_NAME_
- .asciz "Category02"
- .section __TEXT,__objc_methname,cstring_literals
-l_OBJC_METH_VAR_NAME_: ; @OBJC_METH_VAR_NAME_
- .asciz "class02InstanceMethod"
- .section __TEXT,__objc_methtype,cstring_literals
-l_OBJC_METH_VAR_TYPE_: ; @OBJC_METH_VAR_TYPE_
- .asciz "v16 at 0:8"
- .section __TEXT,__objc_methname,cstring_literals
-l_OBJC_METH_VAR_NAME_.1: ; @OBJC_METH_VAR_NAME_.1
- .asciz "myProtocol02Method"
- .section __DATA,__objc_const
- .p2align 3, 0x0 ; @"_OBJC_$_CATEGORY_INSTANCE_METHODS_MyBaseClass_$_Category02"
-__OBJC_$_CATEGORY_INSTANCE_METHODS_MyBaseClass_$_Category02:
- .long 24 ; 0x18
- .long 2 ; 0x2
- .quad l_OBJC_METH_VAR_NAME_
- .quad l_OBJC_METH_VAR_TYPE_
- .quad "-[MyBaseClass(Category02) class02InstanceMethod]"
- .quad l_OBJC_METH_VAR_NAME_.1
- .quad l_OBJC_METH_VAR_TYPE_
- .quad "-[MyBaseClass(Category02) myProtocol02Method]"
- .section __TEXT,__objc_methname,cstring_literals
-l_OBJC_METH_VAR_NAME_.2: ; @OBJC_METH_VAR_NAME_.2
- .asciz "class02ClassMethod"
-l_OBJC_METH_VAR_NAME_.3: ; @OBJC_METH_VAR_NAME_.3
- .asciz "MyProtocol02Prop"
- .section __TEXT,__objc_methtype,cstring_literals
-l_OBJC_METH_VAR_TYPE_.4: ; @OBJC_METH_VAR_TYPE_.4
- .asciz "i16 at 0:8"
- .section __DATA,__objc_const
- .p2align 3, 0x0 ; @"_OBJC_$_CATEGORY_CLASS_METHODS_MyBaseClass_$_Category02"
-__OBJC_$_CATEGORY_CLASS_METHODS_MyBaseClass_$_Category02:
- .long 24 ; 0x18
- .long 2 ; 0x2
- .quad l_OBJC_METH_VAR_NAME_.2
- .quad l_OBJC_METH_VAR_TYPE_
- .quad "+[MyBaseClass(Category02) class02ClassMethod]"
- .quad l_OBJC_METH_VAR_NAME_.3
- .quad l_OBJC_METH_VAR_TYPE_.4
- .quad "+[MyBaseClass(Category02) MyProtocol02Prop]"
- .section __TEXT,__objc_classname,cstring_literals
-l_OBJC_CLASS_NAME_.5: ; @OBJC_CLASS_NAME_.5
- .asciz "MyProtocol02"
- .section __DATA,__objc_const
- .p2align 3, 0x0 ; @"_OBJC_$_PROTOCOL_INSTANCE_METHODS_MyProtocol02"
-__OBJC_$_PROTOCOL_INSTANCE_METHODS_MyProtocol02:
- .long 24 ; 0x18
- .long 2 ; 0x2
- .quad l_OBJC_METH_VAR_NAME_.1
- .quad l_OBJC_METH_VAR_TYPE_
- .quad 0
- .quad l_OBJC_METH_VAR_NAME_.3
- .quad l_OBJC_METH_VAR_TYPE_.4
- .quad 0
- .section __TEXT,__objc_methname,cstring_literals
-l_OBJC_PROP_NAME_ATTR_: ; @OBJC_PROP_NAME_ATTR_
- .asciz "MyProtocol02Prop"
-l_OBJC_PROP_NAME_ATTR_.6: ; @OBJC_PROP_NAME_ATTR_.6
- .asciz "Ti,R"
- .section __DATA,__objc_const
- .p2align 3, 0x0 ; @"_OBJC_$_PROP_LIST_MyProtocol02"
-__OBJC_$_PROP_LIST_MyProtocol02:
- .long 16 ; 0x10
- .long 1 ; 0x1
- .quad l_OBJC_PROP_NAME_ATTR_
- .quad l_OBJC_PROP_NAME_ATTR_.6
- .p2align 3, 0x0 ; @"_OBJC_$_PROTOCOL_METHOD_TYPES_MyProtocol02"
-__OBJC_$_PROTOCOL_METHOD_TYPES_MyProtocol02:
- .quad l_OBJC_METH_VAR_TYPE_
- .quad l_OBJC_METH_VAR_TYPE_.4
- .private_extern __OBJC_PROTOCOL_$_MyProtocol02 ; @"_OBJC_PROTOCOL_$_MyProtocol02"
- .section __DATA,__data
- .globl __OBJC_PROTOCOL_$_MyProtocol02
- .weak_definition __OBJC_PROTOCOL_$_MyProtocol02
- .p2align 3, 0x0
-__OBJC_PROTOCOL_$_MyProtocol02:
- .quad 0
- .quad l_OBJC_CLASS_NAME_.5
- .quad 0
- .quad __OBJC_$_PROTOCOL_INSTANCE_METHODS_MyProtocol02
- .quad 0
- .quad 0
- .quad 0
- .quad __OBJC_$_PROP_LIST_MyProtocol02
- .long 96 ; 0x60
- .long 0 ; 0x0
- .quad __OBJC_$_PROTOCOL_METHOD_TYPES_MyProtocol02
- .quad 0
- .quad 0
- .private_extern __OBJC_LABEL_PROTOCOL_$_MyProtocol02 ; @"_OBJC_LABEL_PROTOCOL_$_MyProtocol02"
- .section __DATA,__objc_protolist,coalesced,no_dead_strip
- .globl __OBJC_LABEL_PROTOCOL_$_MyProtocol02
- .weak_definition __OBJC_LABEL_PROTOCOL_$_MyProtocol02
- .p2align 3, 0x0
-__OBJC_LABEL_PROTOCOL_$_MyProtocol02:
- .quad __OBJC_PROTOCOL_$_MyProtocol02
- .section __DATA,__objc_const
- .p2align 3, 0x0 ; @"_OBJC_CATEGORY_PROTOCOLS_$_MyBaseClass_$_Category02"
-__OBJC_CATEGORY_PROTOCOLS_$_MyBaseClass_$_Category02:
- .quad 1 ; 0x1
- .quad __OBJC_PROTOCOL_$_MyProtocol02
- .quad 0
- .section __TEXT,__objc_methname,cstring_literals
-l_OBJC_PROP_NAME_ATTR_.7: ; @OBJC_PROP_NAME_ATTR_.7
- .asciz "Ti,R,D"
- .section __DATA,__objc_const
- .p2align 3, 0x0 ; @"_OBJC_$_PROP_LIST_MyBaseClass_$_Category02"
-__OBJC_$_PROP_LIST_MyBaseClass_$_Category02:
- .long 16 ; 0x10
- .long 1 ; 0x1
- .quad l_OBJC_PROP_NAME_ATTR_
- .quad l_OBJC_PROP_NAME_ATTR_.7
- .p2align 3, 0x0 ; @"_OBJC_$_CATEGORY_MyBaseClass_$_Category02"
-__OBJC_$_CATEGORY_MyBaseClass_$_Category02:
- .quad l_OBJC_CLASS_NAME_
- .quad _OBJC_CLASS_$_MyBaseClass
- .quad __OBJC_$_CATEGORY_INSTANCE_METHODS_MyBaseClass_$_Category02
- .quad __OBJC_$_CATEGORY_CLASS_METHODS_MyBaseClass_$_Category02
- .quad __OBJC_CATEGORY_PROTOCOLS_$_MyBaseClass_$_Category02
- .quad __OBJC_$_PROP_LIST_MyBaseClass_$_Category02
- .quad 0
- .long 64 ; 0x40
- .space 4
- .section __TEXT,__objc_classname,cstring_literals
-l_OBJC_CLASS_NAME_.8: ; @OBJC_CLASS_NAME_.8
- .asciz "Category03"
- .section __TEXT,__objc_methname,cstring_literals
-l_OBJC_METH_VAR_NAME_.9: ; @OBJC_METH_VAR_NAME_.9
- .asciz "class03InstanceMethod"
-l_OBJC_METH_VAR_NAME_.10: ; @OBJC_METH_VAR_NAME_.10
- .asciz "myProtocol03Method"
- .section __DATA,__objc_const
- .p2align 3, 0x0 ; @"_OBJC_$_CATEGORY_INSTANCE_METHODS_MyBaseClass_$_Category03"
-__OBJC_$_CATEGORY_INSTANCE_METHODS_MyBaseClass_$_Category03:
- .long 24 ; 0x18
- .long 2 ; 0x2
- .quad l_OBJC_METH_VAR_NAME_.9
- .quad l_OBJC_METH_VAR_TYPE_
- .quad "-[MyBaseClass(Category03) class03InstanceMethod]"
- .quad l_OBJC_METH_VAR_NAME_.10
- .quad l_OBJC_METH_VAR_TYPE_
- .quad "-[MyBaseClass(Category03) myProtocol03Method]"
- .section __TEXT,__objc_methname,cstring_literals
-l_OBJC_METH_VAR_NAME_.11: ; @OBJC_METH_VAR_NAME_.11
- .asciz "class03ClassMethod"
-l_OBJC_METH_VAR_NAME_.12: ; @OBJC_METH_VAR_NAME_.12
- .asciz "MyProtocol03Prop"
- .section __DATA,__objc_const
- .p2align 3, 0x0 ; @"_OBJC_$_CATEGORY_CLASS_METHODS_MyBaseClass_$_Category03"
-__OBJC_$_CATEGORY_CLASS_METHODS_MyBaseClass_$_Category03:
- .long 24 ; 0x18
- .long 2 ; 0x2
- .quad l_OBJC_METH_VAR_NAME_.11
- .quad l_OBJC_METH_VAR_TYPE_
- .quad "+[MyBaseClass(Category03) class03ClassMethod]"
- .quad l_OBJC_METH_VAR_NAME_.12
- .quad l_OBJC_METH_VAR_TYPE_.4
- .quad "+[MyBaseClass(Category03) MyProtocol03Prop]"
- .section __TEXT,__objc_classname,cstring_literals
-l_OBJC_CLASS_NAME_.13: ; @OBJC_CLASS_NAME_.13
- .asciz "MyProtocol03"
- .section __DATA,__objc_const
- .p2align 3, 0x0 ; @"_OBJC_$_PROTOCOL_INSTANCE_METHODS_MyProtocol03"
-__OBJC_$_PROTOCOL_INSTANCE_METHODS_MyProtocol03:
- .long 24 ; 0x18
- .long 2 ; 0x2
- .quad l_OBJC_METH_VAR_NAME_.10
- .quad l_OBJC_METH_VAR_TYPE_
- .quad 0
- .quad l_OBJC_METH_VAR_NAME_.12
- .quad l_OBJC_METH_VAR_TYPE_.4
- .quad 0
- .section __TEXT,__objc_methname,cstring_literals
-l_OBJC_PROP_NAME_ATTR_.14: ; @OBJC_PROP_NAME_ATTR_.14
- .asciz "MyProtocol03Prop"
- .section __DATA,__objc_const
- .p2align 3, 0x0 ; @"_OBJC_$_PROP_LIST_MyProtocol03"
-__OBJC_$_PROP_LIST_MyProtocol03:
- .long 16 ; 0x10
- .long 1 ; 0x1
- .quad l_OBJC_PROP_NAME_ATTR_.14
- .quad l_OBJC_PROP_NAME_ATTR_.6
- .p2align 3, 0x0 ; @"_OBJC_$_PROTOCOL_METHOD_TYPES_MyProtocol03"
-__OBJC_$_PROTOCOL_METHOD_TYPES_MyProtocol03:
- .quad l_OBJC_METH_VAR_TYPE_
- .quad l_OBJC_METH_VAR_TYPE_.4
- .private_extern __OBJC_PROTOCOL_$_MyProtocol03 ; @"_OBJC_PROTOCOL_$_MyProtocol03"
- .section __DATA,__data
- .globl __OBJC_PROTOCOL_$_MyProtocol03
- .weak_definition __OBJC_PROTOCOL_$_MyProtocol03
- .p2align 3, 0x0
-__OBJC_PROTOCOL_$_MyProtocol03:
- .quad 0
- .quad l_OBJC_CLASS_NAME_.13
- .quad 0
- .quad __OBJC_$_PROTOCOL_INSTANCE_METHODS_MyProtocol03
- .quad 0
- .quad 0
- .quad 0
- .quad __OBJC_$_PROP_LIST_MyProtocol03
- .long 96 ; 0x60
- .long 0 ; 0x0
- .quad __OBJC_$_PROTOCOL_METHOD_TYPES_MyProtocol03
- .quad 0
- .quad 0
- .private_extern __OBJC_LABEL_PROTOCOL_$_MyProtocol03 ; @"_OBJC_LABEL_PROTOCOL_$_MyProtocol03"
- .section __DATA,__objc_protolist,coalesced,no_dead_strip
- .globl __OBJC_LABEL_PROTOCOL_$_MyProtocol03
- .weak_definition __OBJC_LABEL_PROTOCOL_$_MyProtocol03
- .p2align 3, 0x0
-__OBJC_LABEL_PROTOCOL_$_MyProtocol03:
- .quad __OBJC_PROTOCOL_$_MyProtocol03
- .section __DATA,__objc_const
- .p2align 3, 0x0 ; @"_OBJC_CATEGORY_PROTOCOLS_$_MyBaseClass_$_Category03"
-__OBJC_CATEGORY_PROTOCOLS_$_MyBaseClass_$_Category03:
- .quad 1 ; 0x1
- .quad __OBJC_PROTOCOL_$_MyProtocol03
- .quad 0
- .p2align 3, 0x0 ; @"_OBJC_$_PROP_LIST_MyBaseClass_$_Category03"
-__OBJC_$_PROP_LIST_MyBaseClass_$_Category03:
- .long 16 ; 0x10
- .long 1 ; 0x1
- .quad l_OBJC_PROP_NAME_ATTR_.14
- .quad l_OBJC_PROP_NAME_ATTR_.7
- .p2align 3, 0x0 ; @"_OBJC_$_CATEGORY_MyBaseClass_$_Category03"
-__OBJC_$_CATEGORY_MyBaseClass_$_Category03:
- .quad l_OBJC_CLASS_NAME_.8
- .quad _OBJC_CLASS_$_MyBaseClass
- .quad __OBJC_$_CATEGORY_INSTANCE_METHODS_MyBaseClass_$_Category03
- .quad __OBJC_$_CATEGORY_CLASS_METHODS_MyBaseClass_$_Category03
- .quad __OBJC_CATEGORY_PROTOCOLS_$_MyBaseClass_$_Category03
- .quad __OBJC_$_PROP_LIST_MyBaseClass_$_Category03
- .quad 0
- .long 64 ; 0x40
- .space 4
- .section __DATA,__objc_catlist,regular,no_dead_strip
- .p2align 3, 0x0 ; @"OBJC_LABEL_CATEGORY_$"
-l_OBJC_LABEL_CATEGORY_$:
- .quad __OBJC_$_CATEGORY_MyBaseClass_$_Category02
- .quad __OBJC_$_CATEGORY_MyBaseClass_$_Category03
- .no_dead_strip __OBJC_LABEL_PROTOCOL_$_MyProtocol02
- .no_dead_strip __OBJC_LABEL_PROTOCOL_$_MyProtocol03
- .no_dead_strip __OBJC_PROTOCOL_$_MyProtocol02
- .no_dead_strip __OBJC_PROTOCOL_$_MyProtocol03
- .section __DATA,__objc_imageinfo,regular,no_dead_strip
-L_OBJC_IMAGE_INFO:
- .long 0
- .long 96
-.subsections_via_symbols
diff --git a/lld/test/MachO/objc-category-merging-extern-class-minimal.s b/lld/test/MachO/objc-category-merging-extern-class-minimal.s
deleted file mode 100644
index ede7ef5d9c32d4..00000000000000
--- a/lld/test/MachO/objc-category-merging-extern-class-minimal.s
+++ /dev/null
@@ -1,155 +0,0 @@
-# REQUIRES: aarch64
-# RUN: rm -rf %t; split-file %s %t && cd %t
-
-## Create a dylib with a fake base class to link against
-# RUN: llvm-mc -filetype=obj -triple=arm64-apple-macos -o a64_fakedylib.o a64_fakedylib.s
-# RUN: %lld -arch arm64 a64_fakedylib.o -o a64_fakedylib.dylib -dylib
-
-## Create our main testing dylib - linking against the fake dylib above
-# RUN: llvm-mc -filetype=obj -triple=arm64-apple-macos -o merge_cat_minimal.o merge_cat_minimal.s
-# RUN: %lld -arch arm64 -dylib -o merge_cat_minimal_no_merge.dylib a64_fakedylib.dylib merge_cat_minimal.o
-# RUN: %lld -arch arm64 -dylib -o merge_cat_minimal_merge.dylib -objc_category_merging a64_fakedylib.dylib merge_cat_minimal.o
-
-## Now verify that the flag caused category merging to happen appropriatelly
-# RUN: llvm-objdump --objc-meta-data --macho merge_cat_minimal_no_merge.dylib | FileCheck %s --check-prefixes=NO_MERGE_CATS
-# RUN: llvm-objdump --objc-meta-data --macho merge_cat_minimal_merge.dylib | FileCheck %s --check-prefixes=MERGE_CATS
-
-#### Check merge categories enabled ###
-# Check that the original categories are not there
-MERGE_CATS-NOT: __OBJC_$_CATEGORY_MyBaseClass_$_Category01
-MERGE_CATS-NOT: __OBJC_$_CATEGORY_MyBaseClass_$_Category02
-
-# Check that the merged cateogry is there, in the correct format
-MERGE_CATS: __OBJC_$_CATEGORY_MyBaseClass_$_(Category01|Category02)
-MERGE_CATS-NEXT: name {{.*}} Category01|Category02
-MERGE_CATS: instanceMethods
-MERGE_CATS-NEXT: 24
-MERGE_CATS-NEXT: 2
-MERGE_CATS-NEXT: name {{.*}} cat01_InstanceMethod
-MERGE_CATS-NEXT: types {{.*}} v16 at 0:8
-MERGE_CATS-NEXT: imp -[MyBaseClass(Category01) cat01_InstanceMethod]
-MERGE_CATS-NEXT: name {{.*}} cat02_InstanceMethod
-MERGE_CATS-NEXT: types {{.*}} v16 at 0:8
-MERGE_CATS-NEXT: imp -[MyBaseClass(Category02) cat02_InstanceMethod]
-MERGE_CATS-NEXT: classMethods 0x0
-MERGE_CATS-NEXT: protocols 0x0
-MERGE_CATS-NEXT: instanceProperties 0x0
-
-#### Check merge categories disabled ###
-# Check that the merged category is not there
-NO_MERGE_CATS-NOT: __OBJC_$_CATEGORY_MyBaseClass_$_(Category01|Category02)
-
-# Check that the original categories are there
-NO_MERGE_CATS: __OBJC_$_CATEGORY_MyBaseClass_$_Category01
-NO_MERGE_CATS: __OBJC_$_CATEGORY_MyBaseClass_$_Category02
-
-
-
-#--- a64_fakedylib.s
-
- .section __DATA,__objc_data
- .globl _OBJC_CLASS_$_MyBaseClass
-_OBJC_CLASS_$_MyBaseClass:
- .quad 0
-
-#--- merge_cat_minimal.s
-
-; ================== Generated from ObjC: ==================
-; __attribute__((objc_root_class))
-; @interface MyBaseClass
-; - (void)baseInstanceMethod;
-; @end
-;
-; @interface MyBaseClass(Category01)
-; - (void)cat01_InstanceMethod;
-; @end
-;
-; @implementation MyBaseClass(Category01)
-; - (void)cat01_InstanceMethod {}
-; @end
-;
-; @interface MyBaseClass(Category02)
-; - (void)cat02_InstanceMethod;
-; @end
-;
-; @implementation MyBaseClass(Category02)
-; - (void)cat02_InstanceMethod {}
-; @end
-; ================== Generated from ObjC: ==================
-
- .section __TEXT,__text,regular,pure_instructions
- .p2align 2 ; -- Begin function -[MyBaseClass(Category01) cat01_InstanceMethod]
-"-[MyBaseClass(Category01) cat01_InstanceMethod]": ; @"\01-[MyBaseClass(Category01) cat01_InstanceMethod]"
- .cfi_startproc
- ret
- .cfi_endproc
- ; -- End function
- .p2align 2 ; -- Begin function -[MyBaseClass(Category02) cat02_InstanceMethod]
-"-[MyBaseClass(Category02) cat02_InstanceMethod]": ; @"\01-[MyBaseClass(Category02) cat02_InstanceMethod]"
- .cfi_startproc
- ret
- .cfi_endproc
- ; -- End function
- .section __TEXT,__objc_classname,cstring_literals
-l_OBJC_CLASS_NAME_: ; @OBJC_CLASS_NAME_
- .asciz "Category01"
- .section __TEXT,__objc_methname,cstring_literals
-l_OBJC_METH_VAR_NAME_: ; @OBJC_METH_VAR_NAME_
- .asciz "cat01_InstanceMethod"
- .section __TEXT,__objc_methtype,cstring_literals
-l_OBJC_METH_VAR_TYPE_: ; @OBJC_METH_VAR_TYPE_
- .asciz "v16 at 0:8"
- .section __DATA,__objc_const
- .p2align 3, 0x0 ; @"_OBJC_$_CATEGORY_INSTANCE_METHODS_MyBaseClass_$_Category01"
-__OBJC_$_CATEGORY_INSTANCE_METHODS_MyBaseClass_$_Category01:
- .long 24 ; 0x18
- .long 1 ; 0x1
- .quad l_OBJC_METH_VAR_NAME_
- .quad l_OBJC_METH_VAR_TYPE_
- .quad "-[MyBaseClass(Category01) cat01_InstanceMethod]"
- .p2align 3, 0x0 ; @"_OBJC_$_CATEGORY_MyBaseClass_$_Category01"
-__OBJC_$_CATEGORY_MyBaseClass_$_Category01:
- .quad l_OBJC_CLASS_NAME_
- .quad _OBJC_CLASS_$_MyBaseClass
- .quad __OBJC_$_CATEGORY_INSTANCE_METHODS_MyBaseClass_$_Category01
- .quad 0
- .quad 0
- .quad 0
- .quad 0
- .long 64 ; 0x40
- .space 4
- .section __TEXT,__objc_classname,cstring_literals
-l_OBJC_CLASS_NAME_.1: ; @OBJC_CLASS_NAME_.1
- .asciz "Category02"
- .section __TEXT,__objc_methname,cstring_literals
-l_OBJC_METH_VAR_NAME_.2: ; @OBJC_METH_VAR_NAME_.2
- .asciz "cat02_InstanceMethod"
- .section __DATA,__objc_const
- .p2align 3, 0x0 ; @"_OBJC_$_CATEGORY_INSTANCE_METHODS_MyBaseClass_$_Category02"
-__OBJC_$_CATEGORY_INSTANCE_METHODS_MyBaseClass_$_Category02:
- .long 24 ; 0x18
- .long 1 ; 0x1
- .quad l_OBJC_METH_VAR_NAME_.2
- .quad l_OBJC_METH_VAR_TYPE_
- .quad "-[MyBaseClass(Category02) cat02_InstanceMethod]"
- .p2align 3, 0x0 ; @"_OBJC_$_CATEGORY_MyBaseClass_$_Category02"
-__OBJC_$_CATEGORY_MyBaseClass_$_Category02:
- .quad l_OBJC_CLASS_NAME_.1
- .quad _OBJC_CLASS_$_MyBaseClass
- .quad __OBJC_$_CATEGORY_INSTANCE_METHODS_MyBaseClass_$_Category02
- .quad 0
- .quad 0
- .quad 0
- .quad 0
- .long 64 ; 0x40
- .space 4
- .section __DATA,__objc_catlist,regular,no_dead_strip
- .p2align 3, 0x0 ; @"OBJC_LABEL_CATEGORY_$"
-l_OBJC_LABEL_CATEGORY_$:
- .quad __OBJC_$_CATEGORY_MyBaseClass_$_Category01
- .quad __OBJC_$_CATEGORY_MyBaseClass_$_Category02
- .section __DATA,__objc_imageinfo,regular,no_dead_strip
-L_OBJC_IMAGE_INFO:
- .long 0
- .long 96
-.subsections_via_symbols
More information about the llvm-commits
mailing list