Index: llvm/trunk/include/llvm/BinaryFormat/MachO.h =================================================================== --- llvm/trunk/include/llvm/BinaryFormat/MachO.h +++ llvm/trunk/include/llvm/BinaryFormat/MachO.h @@ -334,6 +334,7 @@ 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: llvm/trunk/include/llvm/MC/MCDirectives.h =================================================================== --- llvm/trunk/include/llvm/MC/MCDirectives.h +++ llvm/trunk/include/llvm/MC/MCDirectives.h @@ -19,6 +19,7 @@ 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: llvm/trunk/include/llvm/MC/MCSymbolMachO.h =================================================================== --- llvm/trunk/include/llvm/MC/MCSymbolMachO.h +++ llvm/trunk/include/llvm/MC/MCSymbolMachO.h @@ -34,6 +34,7 @@ SF_WeakDefinition = 0x0080, SF_SymbolResolver = 0x0100, SF_AltEntry = 0x0200, + SF_Cold = 0x0400, // Common alignment SF_CommonAlignmentMask = 0xF0FF, @@ -97,6 +98,10 @@ 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: llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinter.cpp =================================================================== --- llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -663,6 +663,9 @@ 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: llvm/trunk/lib/MC/MCAsmStreamer.cpp =================================================================== --- llvm/trunk/lib/MC/MCAsmStreamer.cpp +++ llvm/trunk/lib/MC/MCAsmStreamer.cpp @@ -656,6 +656,9 @@ // .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: llvm/trunk/lib/MC/MCELFStreamer.cpp =================================================================== --- llvm/trunk/lib/MC/MCELFStreamer.cpp +++ llvm/trunk/lib/MC/MCELFStreamer.cpp @@ -201,6 +201,7 @@ // 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: llvm/trunk/lib/MC/MCMachOStreamer.cpp =================================================================== --- llvm/trunk/lib/MC/MCMachOStreamer.cpp +++ llvm/trunk/lib/MC/MCMachOStreamer.cpp @@ -386,6 +386,10 @@ Symbol->setWeakDefinition(); Symbol->setWeakReference(); break; + + case MCSA_Cold: + Symbol->setCold(); + break; } return true; Index: llvm/trunk/lib/MC/MCParser/AsmParser.cpp =================================================================== --- llvm/trunk/lib/MC/MCParser/AsmParser.cpp +++ llvm/trunk/lib/MC/MCParser/AsmParser.cpp @@ -426,6 +426,7 @@ DK_WEAK_DEFINITION, DK_WEAK_REFERENCE, DK_WEAK_DEF_CAN_BE_HIDDEN, + DK_COLD, DK_COMM, DK_COMMON, DK_LCOMM, @@ -1983,6 +1984,8 @@ 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 @@ 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; Index: llvm/trunk/test/MC/AArch64/cold.s =================================================================== --- llvm/trunk/test/MC/AArch64/cold.s +++ llvm/trunk/test/MC/AArch64/cold.s @@ -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 Index: llvm/trunk/test/tools/llvm-nm/AArch64/Inputs/cold-func.ll =================================================================== --- llvm/trunk/test/tools/llvm-nm/AArch64/Inputs/cold-func.ll +++ llvm/trunk/test/tools/llvm-nm/AArch64/Inputs/cold-func.ll @@ -0,0 +1,3 @@ +define void @cold_func() cold { + ret void +} Index: llvm/trunk/test/tools/llvm-nm/AArch64/macho-cold.test =================================================================== --- llvm/trunk/test/tools/llvm-nm/AArch64/macho-cold.test +++ llvm/trunk/test/tools/llvm-nm/AArch64/macho-cold.test @@ -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: llvm/trunk/tools/llvm-nm/llvm-nm.cpp =================================================================== --- llvm/trunk/tools/llvm-nm/llvm-nm.cpp +++ llvm/trunk/tools/llvm-nm/llvm-nm.cpp @@ -554,6 +554,11 @@ (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] ";