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
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@352227
91177308-0d34-0410-b5e6-
96231b3b80d8
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,
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
SF_WeakDefinition = 0x0080,
SF_SymbolResolver = 0x0100,
SF_AltEntry = 0x0200,
+ SF_Cold = 0x0400,
// Common alignment
SF_CommonAlignmentMask = 0xF0FF,
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!");
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());
// .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);
// 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:
Symbol->setWeakDefinition();
Symbol->setWeakReference();
break;
+
+ case MCSA_Cold:
+ Symbol->setCold();
+ break;
}
return true;
DK_WEAK_DEFINITION,
DK_WEAK_REFERENCE,
DK_WEAK_DEF_CAN_BE_HIDDEN,
+ DK_COLD,
DK_COMM,
DK_COMMON,
DK_LCOMM,
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);
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;
--- /dev/null
+// 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
--- /dev/null
+define void @cold_func() cold {
+ ret void
+}
--- /dev/null
+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
(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] ";