Skip to content

Commit ece2903

Browse files
alx32Alex B
andauthored
[lld-macho] Implement ObjC category merging (-objc_category_merging) (#82928)
This change adds a flag to lld to enable category merging for MachoO + ObjC. It adds the '-objc_category_merging' flag for enabling this option and uses the existing '-no_objc_category_merging' flag for disabling it. In ld64, this optimization is enabled by default, but in lld, for now, we require explicitly passing the '-objc_category_merging' flag in order to enable it. Behavior: if in the same link unit, multiple categories are extending the same class, then they get merged into a single category. Ex: `Cat1(method1+method2,protocol1) + Cat2(method3+method4,protocol2, property1) = Cat1_2(method1+method2+method3+method4, protocol1+protocol2, property1)` Notes on implementation decisions made in this diff: 1. There is a possibility to further improve the current implementation by directly merging the category data into the base class (if the base class is present in the link unit) - this improvement may be done as a follow-up. This improved functionality is already present in ld64. 2. We do the merging on the raw inputSections - after dead-stripping (categories can't be dead stripped anyway). 3. The changes are mostly self-contained to ObjC.cpp, except for adding a new flag (linkerOptimizeReason) to ConcatInputSection and StringPiece to mark that this data has been optimized away. Another way to do it would have been to just mark the pieces as not 'live' but this would cause the old symbols to show up in the linker map as being dead-stripped - even if dead-stripping is disabled. This flag allows us to match the ld64 behavior. --------- Co-authored-by: Alex B <[email protected]>
1 parent 9a78430 commit ece2903

File tree

7 files changed

+1862
-8
lines changed

7 files changed

+1862
-8
lines changed

lld/MachO/Driver.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1437,6 +1437,8 @@ bool link(ArrayRef<const char *> argsArr, llvm::raw_ostream &stdoutOS,
14371437
resetOutputSegments();
14381438
resetWriter();
14391439
InputFile::resetIdCount();
1440+
1441+
objc::doCleanup();
14401442
};
14411443

14421444
ctx->e.logName = args::getFilenameWithoutExe(argsArr[0]);
@@ -1979,9 +1981,16 @@ bool link(ArrayRef<const char *> argsArr, llvm::raw_ostream &stdoutOS,
19791981
if (config->deadStrip)
19801982
markLive();
19811983

1984+
// Categories are not subject to dead-strip. The __objc_catlist section is
1985+
// marked as NO_DEAD_STRIP and that propagates into all category data.
19821986
if (args.hasArg(OPT_check_category_conflicts))
19831987
objc::checkCategories();
19841988

1989+
// Category merging uses "->live = false" to erase old category data, so
1990+
// it has to run after dead-stripping (markLive).
1991+
if (args.hasArg(OPT_objc_category_merging, OPT_no_objc_category_merging))
1992+
objc::mergeCategories();
1993+
19851994
// ICF assumes that all literals have been folded already, so we must run
19861995
// foldIdenticalLiterals before foldIdenticalSections.
19871996
foldIdenticalLiterals();

lld/MachO/InputSection.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,9 +93,9 @@ class InputSection {
9393
// .subsections_via_symbols, there is typically only one element here.
9494
llvm::TinyPtrVector<Defined *> symbols;
9595

96-
protected:
9796
const Section &section;
9897

98+
protected:
9999
const Defined *getContainingSymbol(uint64_t off) const;
100100
};
101101

0 commit comments

Comments
 (0)