forked from OSchip/llvm-project
[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:
parent
414f9b305d
commit
13ef84fced
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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!");
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -386,6 +386,10 @@ bool MCMachOStreamer::EmitSymbolAttribute(MCSymbol *Sym,
|
|||
Symbol->setWeakDefinition();
|
||||
Symbol->setWeakReference();
|
||||
break;
|
||||
|
||||
case MCSA_Cold:
|
||||
Symbol->setCold();
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
|
@ -0,0 +1,3 @@
|
|||
define void @cold_func() cold {
|
||||
ret void
|
||||
}
|
|
@ -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
|
|
@ -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] ";
|
||||
|
||||
|
|
Loading…
Reference in New Issue