]> granicus.if.org Git - llvm/commitdiff
[MC] Teach the MachO object writer about N_FUNC_COLD
authorVedant Kumar <vsk@apple.com>
Fri, 25 Jan 2019 18:30:22 +0000 (18:30 +0000)
committerVedant Kumar <vsk@apple.com>
Fri, 25 Jan 2019 18:30:22 +0000 (18:30 +0000)
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

12 files changed:
include/llvm/BinaryFormat/MachO.h
include/llvm/MC/MCDirectives.h
include/llvm/MC/MCSymbolMachO.h
lib/CodeGen/AsmPrinter/AsmPrinter.cpp
lib/MC/MCAsmStreamer.cpp
lib/MC/MCELFStreamer.cpp
lib/MC/MCMachOStreamer.cpp
lib/MC/MCParser/AsmParser.cpp
test/MC/AArch64/cold.s [new file with mode: 0644]
test/tools/llvm-nm/AArch64/Inputs/cold-func.ll [new file with mode: 0644]
test/tools/llvm-nm/AArch64/macho-cold.test [new file with mode: 0644]
tools/llvm-nm/llvm-nm.cpp

index 372fc902f77e7de89c6d7ef7e95146b886984d1e..08fe7803d408ba54894ac9416008f72e2c1ddcc5 100644 (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,
index e13a11b088eb836f436e9a82642f381bfd6fe8f5..4029264c202635910e5637d205fa5258dc2522cf 100644 (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
index 9f5cb0b5c6df051b0fea868c603c44db9a9a819c..8f9ff56470a77432845d9c2e6b4c22f91a806cba 100644 (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!");
index aed46d58f99a3aa89f61e4cf5f241540cf69acac..4c9fe59af425e99d1802b8d160adcfced87df68d 100644 (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());
index cc473eae118d2dfaa1d4e57bce426fc324932cd0..b18c82309ac669929da9686681e88f65228b826c 100644 (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);
index 6954692a0ef3e88e2f0f4d0ac7a4924221fd57ff..6fe16abd5a3a692555509af77f11825772e327ab 100644 (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:
index 7e368a8f1ad062a822a1e713eb8cdc78233d24a1..613f255a4ea47cfb9d19ce96288f07a6989010a2 100644 (file)
@@ -386,6 +386,10 @@ bool MCMachOStreamer::EmitSymbolAttribute(MCSymbol *Sym,
     Symbol->setWeakDefinition();
     Symbol->setWeakReference();
     break;
+
+  case MCSA_Cold:
+    Symbol->setCold();
+    break;
   }
 
   return true;
index 6c311c138369b2693af9884cde8e130ec3320c1c..189422e2ad35b12c61313365a33a31d428e5dfaf 100644 (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;
diff --git a/test/MC/AArch64/cold.s b/test/MC/AArch64/cold.s
new file mode 100644 (file)
index 0000000..44cb52f
--- /dev/null
@@ -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
diff --git a/test/tools/llvm-nm/AArch64/Inputs/cold-func.ll b/test/tools/llvm-nm/AArch64/Inputs/cold-func.ll
new file mode 100644 (file)
index 0000000..686e67e
--- /dev/null
@@ -0,0 +1,3 @@
+define void @cold_func() cold {
+  ret void
+}
diff --git a/test/tools/llvm-nm/AArch64/macho-cold.test b/test/tools/llvm-nm/AArch64/macho-cold.test
new file mode 100644 (file)
index 0000000..a07f5d2
--- /dev/null
@@ -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
index 08ea238ac3ae8af96a5a65f59793cf4ea4dfa639..f81e909c924a8a99da65caabf0056414754955cc 100644 (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] ";