Skip to content

Commit

Permalink
[lld-macho] Implement ObjC category merging (-objc_category_merging) (l…
Browse files Browse the repository at this point in the history
…lvm#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]>
  • Loading branch information
alx32 and Alex B authored Mar 18, 2024
1 parent 9a78430 commit ece2903
Show file tree
Hide file tree
Showing 7 changed files with 1,862 additions and 8 deletions.
9 changes: 9 additions & 0 deletions lld/MachO/Driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1437,6 +1437,8 @@ bool link(ArrayRef<const char *> argsArr, llvm::raw_ostream &stdoutOS,
resetOutputSegments();
resetWriter();
InputFile::resetIdCount();

objc::doCleanup();
};

ctx->e.logName = args::getFilenameWithoutExe(argsArr[0]);
Expand Down Expand Up @@ -1979,9 +1981,16 @@ 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();
Expand Down
2 changes: 1 addition & 1 deletion lld/MachO/InputSection.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,9 +93,9 @@ class InputSection {
// .subsections_via_symbols, there is typically only one element here.
llvm::TinyPtrVector<Defined *> symbols;

protected:
const Section &section;

protected:
const Defined *getContainingSymbol(uint64_t off) const;
};

Expand Down
Loading

0 comments on commit ece2903

Please sign in to comment.