[MC] Teach the MachO object writer about N_FUNC_COLD

N_FUNC_COLD is a new MachO symbol attribute. It's a hint to the linker
to order a symbol towards the end of its section, to improve locality.

Example:

```
void a1() {}
__attribute__((cold)) void a2() {}
void a3() {}
int main() {
  a1();
  a2();
  a3();
  return 0;
}
```

A linker that supports N_FUNC_COLD will order _a2 to the end of the text
section. From `nm -njU` output, we see:

```
_a1
_a3
_main
_a2
```

Differential Revision: https://reviews.llvm.org/D57190

llvm-svn: 352227
This commit is contained in:
Vedant Kumar 2019-01-25 18:30:22 +00:00
parent 414f9b305d
commit 13ef84fced
12 changed files with 47 additions and 0 deletions

View File

@ -334,6 +334,7 @@ enum {
N_WEAK_DEF = 0x0080u,
N_SYMBOL_RESOLVER = 0x0100u,
N_ALT_ENTRY = 0x0200u,
N_COLD_FUNC = 0x0400u,
// For undefined symbols coming from libraries, see GET_LIBRARY_ORDINAL()
// as these are in the top 8 bits.
SELF_LIBRARY_ORDINAL = 0x0,

View File

@ -19,6 +19,7 @@ enum MCSymbolAttr {
MCSA_Invalid = 0, ///< Not a valid directive.
// Various directives in alphabetical order.
MCSA_Cold, ///< .cold (MachO)
MCSA_ELF_TypeFunction, ///< .type _foo, STT_FUNC # aka @function
MCSA_ELF_TypeIndFunction, ///< .type _foo, STT_GNU_IFUNC
MCSA_ELF_TypeObject, ///< .type _foo, STT_OBJECT # aka @object

View File

@ -34,6 +34,7 @@ class MCSymbolMachO : public MCSymbol {
SF_WeakDefinition = 0x0080,
SF_SymbolResolver = 0x0100,
SF_AltEntry = 0x0200,
SF_Cold = 0x0400,
// Common alignment
SF_CommonAlignmentMask = 0xF0FF,
@ -97,6 +98,10 @@ public:
return getFlags() & SF_AltEntry;
}
void setCold() const { modifyFlags(SF_Cold, SF_Cold); }
bool isCold() const { return getFlags() & SF_Cold; }
void setDesc(unsigned Value) const {
assert(Value == (Value & SF_DescFlagsMask) &&
"Invalid .desc value!");

View File

@ -663,6 +663,9 @@ void AsmPrinter::EmitFunctionHeader() {
if (MAI->hasDotTypeDotSizeDirective())
OutStreamer->EmitSymbolAttribute(CurrentFnSym, MCSA_ELF_TypeFunction);
if (F.hasFnAttribute(Attribute::Cold))
OutStreamer->EmitSymbolAttribute(CurrentFnSym, MCSA_Cold);
if (isVerbose()) {
F.printAsOperand(OutStreamer->GetCommentOS(),
/*PrintType=*/false, F.getParent());

View File

@ -656,6 +656,9 @@ bool MCAsmStreamer::EmitSymbolAttribute(MCSymbol *Symbol,
// .weak_reference
case MCSA_WeakReference: OS << MAI->getWeakRefDirective(); break;
case MCSA_WeakDefAutoPrivate: OS << "\t.weak_def_can_be_hidden\t"; break;
case MCSA_Cold:
// Assemblers currently do not support a .cold directive.
return false;
}
Symbol->print(OS, MAI);

View File

@ -201,6 +201,7 @@ bool MCELFStreamer::EmitSymbolAttribute(MCSymbol *S, MCSymbolAttr Attribute) {
// In the future it might be worth trying to make these operations more well
// defined.
switch (Attribute) {
case MCSA_Cold:
case MCSA_LazyReference:
case MCSA_Reference:
case MCSA_SymbolResolver:

View File

@ -386,6 +386,10 @@ bool MCMachOStreamer::EmitSymbolAttribute(MCSymbol *Sym,
Symbol->setWeakDefinition();
Symbol->setWeakReference();
break;
case MCSA_Cold:
Symbol->setCold();
break;
}
return true;

View File

@ -426,6 +426,7 @@ private:
DK_WEAK_DEFINITION,
DK_WEAK_REFERENCE,
DK_WEAK_DEF_CAN_BE_HIDDEN,
DK_COLD,
DK_COMM,
DK_COMMON,
DK_LCOMM,
@ -1983,6 +1984,8 @@ bool AsmParser::parseStatement(ParseStatementInfo &Info,
return parseDirectiveSymbolAttribute(MCSA_WeakReference);
case DK_WEAK_DEF_CAN_BE_HIDDEN:
return parseDirectiveSymbolAttribute(MCSA_WeakDefAutoPrivate);
case DK_COLD:
return parseDirectiveSymbolAttribute(MCSA_Cold);
case DK_COMM:
case DK_COMMON:
return parseDirectiveComm(/*IsLocal=*/false);
@ -5223,6 +5226,7 @@ void AsmParser::initializeDirectiveKindMap() {
DirectiveKindMap[".weak_definition"] = DK_WEAK_DEFINITION;
DirectiveKindMap[".weak_reference"] = DK_WEAK_REFERENCE;
DirectiveKindMap[".weak_def_can_be_hidden"] = DK_WEAK_DEF_CAN_BE_HIDDEN;
DirectiveKindMap[".cold"] = DK_COLD;
DirectiveKindMap[".comm"] = DK_COMM;
DirectiveKindMap[".common"] = DK_COMMON;
DirectiveKindMap[".lcomm"] = DK_LCOMM;

View File

@ -0,0 +1,13 @@
// RUN: llvm-mc -triple aarch64-apple-ios -o - -filetype=obj %s | \
// RUN: llvm-readobj -symbols | FileCheck %s -check-prefix=READOBJ
// READOBJ-LABEL: Name: cold_func
// READOBJ-NEXT: Type: Section
// READOBJ-NEXT: Section: __text
// READOBJ-NEXT: RefType: UndefinedNonLazy (0x0)
// READOBJ-NEXT: Flags [ (0x400)
.text
.cold cold_func
cold_func:
ret

View File

@ -0,0 +1,3 @@
define void @cold_func() cold {
ret void
}

View File

@ -0,0 +1,4 @@
RUN: llc -O0 -mtriple=aarch64-apple-ios %p/Inputs/cold-func.ll -filetype=obj -o %t.aarch64.o
RUN: llvm-nm -m %t.aarch64.o | FileCheck %s
CHECK: [cold] _cold_func

View File

@ -554,6 +554,11 @@ static void darwinPrintSymbol(SymbolicFile &Obj, SymbolListT::iterator I,
(NDesc & MachO::N_ALT_ENTRY) == MachO::N_ALT_ENTRY)
outs() << "[alt entry] ";
if (Filetype == MachO::MH_OBJECT &&
((NType & MachO::N_TYPE) != MachO::N_UNDF) &&
(NDesc & MachO::N_COLD_FUNC) == MachO::N_COLD_FUNC)
outs() << "[cold] ";
if ((NDesc & MachO::N_ARM_THUMB_DEF) == MachO::N_ARM_THUMB_DEF)
outs() << "[Thumb] ";