[llvm] r333823 - [MC] Add assembler support for .cg_profile.
Michael J. Spencer via llvm-commits
llvm-commits at lists.llvm.org
Sat Jun 2 09:33:01 PDT 2018
Author: mspencer
Date: Sat Jun 2 09:33:01 2018
New Revision: 333823
URL: http://llvm.org/viewvc/llvm-project?rev=333823&view=rev
Log:
[MC] Add assembler support for .cg_profile.
Object FIle Representation
At codegen time this is emitted into the ELF file a pair of symbol indices and a weight. In assembly it looks like:
.cg_profile a, b, 32
.cg_profile freq, a, 11
.cg_profile freq, b, 20
When writing an ELF file these are put into a SHT_LLVM_CALL_GRAPH_PROFILE (0x6fff4c02) section as (uint32_t, uint32_t, uint64_t) tuples as (from symbol index, to symbol index, weight).
Differential Revision: https://reviews.llvm.org/D44965
Added:
llvm/trunk/test/MC/AsmParser/directive_cgprofile.s
llvm/trunk/test/MC/ELF/cgprofile-error.s
llvm/trunk/test/MC/ELF/cgprofile.s
Modified:
llvm/trunk/docs/Extensions.rst
llvm/trunk/include/llvm/BinaryFormat/ELF.h
llvm/trunk/include/llvm/MC/MCAssembler.h
llvm/trunk/include/llvm/MC/MCELFStreamer.h
llvm/trunk/include/llvm/MC/MCStreamer.h
llvm/trunk/include/llvm/Object/ELFTypes.h
llvm/trunk/lib/MC/ELFObjectWriter.cpp
llvm/trunk/lib/MC/MCAsmStreamer.cpp
llvm/trunk/lib/MC/MCELFStreamer.cpp
llvm/trunk/lib/MC/MCParser/ELFAsmParser.cpp
llvm/trunk/lib/MC/MCSectionELF.cpp
llvm/trunk/lib/MC/MCStreamer.cpp
llvm/trunk/lib/Object/ELF.cpp
llvm/trunk/lib/ObjectYAML/ELFYAML.cpp
llvm/trunk/tools/llvm-readobj/ELFDumper.cpp
llvm/trunk/tools/llvm-readobj/ObjDumper.h
llvm/trunk/tools/llvm-readobj/llvm-readobj.cpp
Modified: llvm/trunk/docs/Extensions.rst
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/Extensions.rst?rev=333823&r1=333822&r2=333823&view=diff
==============================================================================
--- llvm/trunk/docs/Extensions.rst (original)
+++ llvm/trunk/docs/Extensions.rst Sat Jun 2 09:33:01 2018
@@ -285,6 +285,50 @@ The following directives are specified:
The paramter identifies an additional library search path to be considered
when looking up libraries after the inclusion of this option.
+``SHT_LLVM_CALL_GRAPH_PROFILE`` Section (Call Graph Profile)
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+This section is used to pass a call graph profile to the linker which can be
+used to optimize the placement of sections. It contains a sequence of
+(from symbol, to symbol, weight) tuples.
+
+It shall have a type of ``SHT_LLVM_CALL_GRAPH_PROFILE`` (0x6fff4c02), shall
+have the ``SHF_EXCLUDE`` flag set, the ``sh_link`` member shall hold the section
+header index of the associated symbol table, and shall have a ``sh_entsize`` of
+16. It should be named ``.llvm.call-graph-profile``.
+
+The contents of the section shall be a sequence of ``Elf_CGProfile`` entries.
+
+.. code-block:: c
+
+ typedef struct {
+ Elf_Word cgp_from;
+ Elf_Word cgp_to;
+ Elf_Xword cgp_weight;
+ } Elf_CGProfile;
+
+cgp_from
+ The symbol index of the source of the edge.
+
+cgp_to
+ The symbol index of the destination of the edge.
+
+cgp_weight
+ The weight of the edge.
+
+This is represented in assembly as:
+
+.. code-block:: gas
+
+ .cg_profile from, to, 42
+
+``.cg_profile`` directives are processed at the end of the file. It is an error
+if either ``from`` or ``to`` are undefined temporary symbols. If either symbol
+is a temporary symbol, then the section symbol is used instead. If either
+symbol is undefined, then that symbol is defined as if ``.weak symbol`` has been
+written at the end of the file. This forces the symbol to show up in the symbol
+table.
+
Target Specific Behaviour
=========================
Modified: llvm/trunk/include/llvm/BinaryFormat/ELF.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/BinaryFormat/ELF.h?rev=333823&r1=333822&r2=333823&view=diff
==============================================================================
--- llvm/trunk/include/llvm/BinaryFormat/ELF.h (original)
+++ llvm/trunk/include/llvm/BinaryFormat/ELF.h Sat Jun 2 09:33:01 2018
@@ -803,6 +803,7 @@ enum : unsigned {
SHT_ANDROID_RELA = 0x60000002,
SHT_LLVM_ODRTAB = 0x6fff4c00, // LLVM ODR table.
SHT_LLVM_LINKER_OPTIONS = 0x6fff4c01, // LLVM Linker Options.
+ SHT_LLVM_CALL_GRAPH_PROFILE = 0x6fff4c02, // LLVM Call Graph Profile.
SHT_GNU_ATTRIBUTES = 0x6ffffff5, // Object attributes.
SHT_GNU_HASH = 0x6ffffff6, // GNU-style hash table.
SHT_GNU_verdef = 0x6ffffffd, // GNU version definitions.
Modified: llvm/trunk/include/llvm/MC/MCAssembler.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/MC/MCAssembler.h?rev=333823&r1=333822&r2=333823&view=diff
==============================================================================
--- llvm/trunk/include/llvm/MC/MCAssembler.h (original)
+++ llvm/trunk/include/llvm/MC/MCAssembler.h Sat Jun 2 09:33:01 2018
@@ -418,6 +418,13 @@ public:
const MCLOHContainer &getLOHContainer() const {
return const_cast<MCAssembler *>(this)->getLOHContainer();
}
+
+ struct CGProfileEntry {
+ const MCSymbolRefExpr *From;
+ const MCSymbolRefExpr *To;
+ uint64_t Count;
+ };
+ std::vector<CGProfileEntry> CGProfile;
/// @}
/// \name Backend Data Access
/// @{
Modified: llvm/trunk/include/llvm/MC/MCELFStreamer.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/MC/MCELFStreamer.h?rev=333823&r1=333822&r2=333823&view=diff
==============================================================================
--- llvm/trunk/include/llvm/MC/MCELFStreamer.h (original)
+++ llvm/trunk/include/llvm/MC/MCELFStreamer.h Sat Jun 2 09:33:01 2018
@@ -69,6 +69,9 @@ public:
void EmitValueToAlignment(unsigned, int64_t, unsigned, unsigned) override;
+ void emitCGProfileEntry(const MCSymbolRefExpr *From,
+ const MCSymbolRefExpr *To, uint64_t Count) override;
+
void FinishImpl() override;
void EmitBundleAlignMode(unsigned AlignPow2) override;
@@ -81,6 +84,8 @@ private:
void EmitInstToData(const MCInst &Inst, const MCSubtargetInfo &) override;
void fixSymbolsInTLSFixups(const MCExpr *expr);
+ void finalizeCGProfileEntry(const MCSymbolRefExpr *&S);
+ void finalizeCGProfile();
/// Merge the content of the fragment \p EF into the fragment \p DF.
void mergeFragment(MCDataFragment *, MCDataFragment *);
Modified: llvm/trunk/include/llvm/MC/MCStreamer.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/MC/MCStreamer.h?rev=333823&r1=333822&r2=333823&view=diff
==============================================================================
--- llvm/trunk/include/llvm/MC/MCStreamer.h (original)
+++ llvm/trunk/include/llvm/MC/MCStreamer.h Sat Jun 2 09:33:01 2018
@@ -901,6 +901,9 @@ public:
SMLoc Loc = SMLoc());
virtual void EmitWinEHHandlerData(SMLoc Loc = SMLoc());
+ virtual void emitCGProfileEntry(const MCSymbolRefExpr *From,
+ const MCSymbolRefExpr *To, uint64_t Count);
+
/// Get the .pdata section used for the given section. Typically the given
/// section is either the main .text section or some other COMDAT .text
/// section, but it may be any section containing code.
Modified: llvm/trunk/include/llvm/Object/ELFTypes.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Object/ELFTypes.h?rev=333823&r1=333822&r2=333823&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Object/ELFTypes.h (original)
+++ llvm/trunk/include/llvm/Object/ELFTypes.h Sat Jun 2 09:33:01 2018
@@ -43,6 +43,7 @@ template <class ELFT> struct Elf_Chdr_Im
template <class ELFT> struct Elf_Nhdr_Impl;
template <class ELFT> class Elf_Note_Impl;
template <class ELFT> class Elf_Note_Iterator_Impl;
+template <class ELFT> struct Elf_CGProfile_Impl;
template <endianness E, bool Is64> struct ELFType {
private:
@@ -72,6 +73,7 @@ public:
using Nhdr = Elf_Nhdr_Impl<ELFType<E, Is64>>;
using Note = Elf_Note_Impl<ELFType<E, Is64>>;
using NoteIterator = Elf_Note_Iterator_Impl<ELFType<E, Is64>>;
+ using CGProfile = Elf_CGProfile_Impl<ELFType<E, Is64>>;
using DynRange = ArrayRef<Dyn>;
using ShdrRange = ArrayRef<Shdr>;
using SymRange = ArrayRef<Sym>;
@@ -678,6 +680,13 @@ public:
}
};
+template <class ELFT> struct Elf_CGProfile_Impl {
+ LLVM_ELF_IMPORT_TYPES_ELFT(ELFT)
+ Elf_Word cgp_from;
+ Elf_Word cgp_to;
+ Elf_Xword cgp_weight;
+};
+
// MIPS .reginfo section
template <class ELFT>
struct Elf_Mips_RegInfo;
Modified: llvm/trunk/lib/MC/ELFObjectWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/ELFObjectWriter.cpp?rev=333823&r1=333822&r2=333823&view=diff
==============================================================================
--- llvm/trunk/lib/MC/ELFObjectWriter.cpp (original)
+++ llvm/trunk/lib/MC/ELFObjectWriter.cpp Sat Jun 2 09:33:01 2018
@@ -976,6 +976,7 @@ void ELFWriter::writeSection(const Secti
break;
case ELF::SHT_SYMTAB_SHNDX:
+ case ELF::SHT_LLVM_CALL_GRAPH_PROFILE:
sh_link = SymbolTableIndex;
break;
@@ -1091,6 +1092,14 @@ uint64_t ELFWriter::writeObject(MCAssemb
}
}
+ MCSectionELF *CGProfileSection = nullptr;
+ if (!Asm.CGProfile.empty()) {
+ CGProfileSection = Ctx.getELFSection(".llvm.call-graph-profile",
+ ELF::SHT_LLVM_CALL_GRAPH_PROFILE,
+ ELF::SHF_EXCLUDE, 16, "");
+ SectionIndexMap[CGProfileSection] = addToSectionTable(CGProfileSection);
+ }
+
for (MCSectionELF *Group : Groups) {
align(Group->getAlignment());
@@ -1132,6 +1141,17 @@ uint64_t ELFWriter::writeObject(MCAssemb
}
}
+ if (CGProfileSection) {
+ uint64_t SecStart = W.OS.tell();
+ for (const MCAssembler::CGProfileEntry &CGPE : Asm.CGProfile) {
+ W.write<uint32_t>(CGPE.From->getSymbol().getIndex());
+ W.write<uint32_t>(CGPE.To->getSymbol().getIndex());
+ W.write<uint64_t>(CGPE.Count);
+ }
+ uint64_t SecEnd = W.OS.tell();
+ SectionOffsets[CGProfileSection] = std::make_pair(SecStart, SecEnd);
+ }
+
{
uint64_t SecStart = W.OS.tell();
const MCSectionELF *Sec = createStringTable(Ctx);
Modified: llvm/trunk/lib/MC/MCAsmStreamer.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCAsmStreamer.cpp?rev=333823&r1=333822&r2=333823&view=diff
==============================================================================
--- llvm/trunk/lib/MC/MCAsmStreamer.cpp (original)
+++ llvm/trunk/lib/MC/MCAsmStreamer.cpp Sat Jun 2 09:33:01 2018
@@ -304,6 +304,9 @@ public:
SMLoc Loc) override;
void EmitWinEHHandlerData(SMLoc Loc) override;
+ void emitCGProfileEntry(const MCSymbolRefExpr *From,
+ const MCSymbolRefExpr *To, uint64_t Count) override;
+
void EmitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI,
bool PrintSchedInfo) override;
@@ -1650,6 +1653,17 @@ void MCAsmStreamer::EmitWinCFIEndProlog(
EmitEOL();
}
+void MCAsmStreamer::emitCGProfileEntry(const MCSymbolRefExpr *From,
+ const MCSymbolRefExpr *To,
+ uint64_t Count) {
+ OS << "\t.cg_profile ";
+ From->getSymbol().print(OS, MAI);
+ OS << ", ";
+ To->getSymbol().print(OS, MAI);
+ OS << ", " << Count;
+ EmitEOL();
+}
+
void MCAsmStreamer::AddEncodingComment(const MCInst &Inst,
const MCSubtargetInfo &STI,
bool PrintSchedInfo) {
Modified: llvm/trunk/lib/MC/MCELFStreamer.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCELFStreamer.cpp?rev=333823&r1=333822&r2=333823&view=diff
==============================================================================
--- llvm/trunk/lib/MC/MCELFStreamer.cpp (original)
+++ llvm/trunk/lib/MC/MCELFStreamer.cpp Sat Jun 2 09:33:01 2018
@@ -355,6 +355,12 @@ void MCELFStreamer::EmitValueToAlignment
ValueSize, MaxBytesToEmit);
}
+void MCELFStreamer::emitCGProfileEntry(const MCSymbolRefExpr *From,
+ const MCSymbolRefExpr *To,
+ uint64_t Count) {
+ getAssembler().CGProfile.push_back({From, To, Count});
+}
+
void MCELFStreamer::EmitIdent(StringRef IdentString) {
MCSection *Comment = getAssembler().getContext().getELFSection(
".comment", ELF::SHT_PROGBITS, ELF::SHF_MERGE | ELF::SHF_STRINGS, 1, "");
@@ -447,6 +453,37 @@ void MCELFStreamer::fixSymbolsInTLSFixup
}
}
+void MCELFStreamer::finalizeCGProfileEntry(const MCSymbolRefExpr *&SRE) {
+ const MCSymbol *S = &SRE->getSymbol();
+ if (S->isTemporary()) {
+ if (!S->isInSection()) {
+ getContext().reportError(
+ SRE->getLoc(), Twine("Reference to undefined temporary symbol ") +
+ "`" + S->getName() + "`");
+ return;
+ }
+ S = S->getSection().getBeginSymbol();
+ S->setUsedInReloc();
+ SRE =
+ MCSymbolRefExpr::create(S, SRE->getKind(), getContext(), SRE->getLoc());
+ return;
+ }
+ // Not a temporary, referece it as a weak undefined.
+ bool Created;
+ getAssembler().registerSymbol(*S, &Created);
+ if (Created) {
+ cast<MCSymbolELF>(S)->setBinding(ELF::STB_WEAK);
+ cast<MCSymbolELF>(S)->setExternal(true);
+ }
+}
+
+void MCELFStreamer::finalizeCGProfile() {
+ for (MCAssembler::CGProfileEntry &E : getAssembler().CGProfile) {
+ finalizeCGProfileEntry(E.From);
+ finalizeCGProfileEntry(E.To);
+ }
+}
+
void MCELFStreamer::EmitInstToFragment(const MCInst &Inst,
const MCSubtargetInfo &STI) {
this->MCObjectStreamer::EmitInstToFragment(Inst, STI);
@@ -612,6 +649,7 @@ void MCELFStreamer::FinishImpl() {
MCSection *CurSection = getCurrentSectionOnly();
setSectionAlignmentForBundling(getAssembler(), CurSection);
+ finalizeCGProfile();
EmitFrames(nullptr);
this->MCObjectStreamer::FinishImpl();
Modified: llvm/trunk/lib/MC/MCParser/ELFAsmParser.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCParser/ELFAsmParser.cpp?rev=333823&r1=333822&r2=333823&view=diff
==============================================================================
--- llvm/trunk/lib/MC/MCParser/ELFAsmParser.cpp (original)
+++ llvm/trunk/lib/MC/MCParser/ELFAsmParser.cpp Sat Jun 2 09:33:01 2018
@@ -85,6 +85,7 @@ public:
addDirectiveHandler<
&ELFAsmParser::ParseDirectiveSymbolAttribute>(".hidden");
addDirectiveHandler<&ELFAsmParser::ParseDirectiveSubsection>(".subsection");
+ addDirectiveHandler<&ELFAsmParser::ParseDirectiveCGProfile>(".cg_profile");
}
// FIXME: Part of this logic is duplicated in the MCELFStreamer. What is
@@ -149,6 +150,7 @@ public:
bool ParseDirectiveWeakref(StringRef, SMLoc);
bool ParseDirectiveSymbolAttribute(StringRef, SMLoc);
bool ParseDirectiveSubsection(StringRef, SMLoc);
+ bool ParseDirectiveCGProfile(StringRef, SMLoc);
private:
bool ParseSectionName(StringRef &SectionName);
@@ -610,6 +612,8 @@ EndStmt:
Type = ELF::SHT_LLVM_ODRTAB;
else if (TypeName == "llvm_linker_options")
Type = ELF::SHT_LLVM_LINKER_OPTIONS;
+ else if (TypeName == "llvm_call_graph_profile")
+ Type = ELF::SHT_LLVM_CALL_GRAPH_PROFILE;
else if (TypeName.getAsInteger(0, Type))
return TokError("unknown section type");
}
@@ -840,6 +844,47 @@ bool ELFAsmParser::ParseDirectiveSubsect
return false;
}
+/// ParseDirectiveCGProfile
+/// ::= .cg_profile identifier, identifier, <number>
+bool ELFAsmParser::ParseDirectiveCGProfile(StringRef, SMLoc) {
+ StringRef From;
+ SMLoc FromLoc = getLexer().getLoc();
+ if (getParser().parseIdentifier(From))
+ return TokError("expected identifier in directive");
+
+ if (getLexer().isNot(AsmToken::Comma))
+ return TokError("expected a comma");
+ Lex();
+
+ StringRef To;
+ SMLoc ToLoc = getLexer().getLoc();
+ if (getParser().parseIdentifier(To))
+ return TokError("expected identifier in directive");
+
+ if (getLexer().isNot(AsmToken::Comma))
+ return TokError("expected a comma");
+ Lex();
+
+ int64_t Count;
+ if (getParser().parseIntToken(
+ Count, "expected integer count in '.cg_profile' directive"))
+ return true;
+
+ if (getLexer().isNot(AsmToken::EndOfStatement))
+ return TokError("unexpected token in directive");
+
+ MCSymbol *FromSym = getContext().getOrCreateSymbol(From);
+ MCSymbol *ToSym = getContext().getOrCreateSymbol(To);
+
+ getStreamer().emitCGProfileEntry(
+ MCSymbolRefExpr::create(FromSym, MCSymbolRefExpr::VK_None, getContext(),
+ FromLoc),
+ MCSymbolRefExpr::create(ToSym, MCSymbolRefExpr::VK_None, getContext(),
+ ToLoc),
+ Count);
+ return false;
+}
+
namespace llvm {
MCAsmParserExtension *createELFAsmParser() {
Modified: llvm/trunk/lib/MC/MCSectionELF.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCSectionELF.cpp?rev=333823&r1=333822&r2=333823&view=diff
==============================================================================
--- llvm/trunk/lib/MC/MCSectionELF.cpp (original)
+++ llvm/trunk/lib/MC/MCSectionELF.cpp Sat Jun 2 09:33:01 2018
@@ -150,6 +150,8 @@ void MCSectionELF::PrintSwitchToSection(
OS << "llvm_odrtab";
else if (Type == ELF::SHT_LLVM_LINKER_OPTIONS)
OS << "llvm_linker_options";
+ else if (Type == ELF::SHT_LLVM_CALL_GRAPH_PROFILE)
+ OS << "llvm_call_graph_profile";
else
report_fatal_error("unsupported type 0x" + Twine::utohexstr(Type) +
" for section " + getSectionName());
Modified: llvm/trunk/lib/MC/MCStreamer.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCStreamer.cpp?rev=333823&r1=333822&r2=333823&view=diff
==============================================================================
--- llvm/trunk/lib/MC/MCStreamer.cpp (original)
+++ llvm/trunk/lib/MC/MCStreamer.cpp Sat Jun 2 09:33:01 2018
@@ -661,6 +661,10 @@ void MCStreamer::EmitWinEHHandlerData(SM
getContext().reportError(Loc, "Chained unwind areas can't have handlers!");
}
+void MCStreamer::emitCGProfileEntry(const MCSymbolRefExpr *From,
+ const MCSymbolRefExpr *To, uint64_t Count) {
+}
+
static MCSection *getWinCFISection(MCContext &Context, unsigned *NextWinCFIID,
MCSection *MainCFISec,
const MCSection *TextSec) {
Modified: llvm/trunk/lib/Object/ELF.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Object/ELF.cpp?rev=333823&r1=333822&r2=333823&view=diff
==============================================================================
--- llvm/trunk/lib/Object/ELF.cpp (original)
+++ llvm/trunk/lib/Object/ELF.cpp Sat Jun 2 09:33:01 2018
@@ -206,6 +206,7 @@ StringRef llvm::object::getELFSectionTyp
STRINGIFY_ENUM_CASE(ELF, SHT_ANDROID_RELA);
STRINGIFY_ENUM_CASE(ELF, SHT_LLVM_ODRTAB);
STRINGIFY_ENUM_CASE(ELF, SHT_LLVM_LINKER_OPTIONS);
+ STRINGIFY_ENUM_CASE(ELF, SHT_LLVM_CALL_GRAPH_PROFILE);
STRINGIFY_ENUM_CASE(ELF, SHT_GNU_ATTRIBUTES);
STRINGIFY_ENUM_CASE(ELF, SHT_GNU_HASH);
STRINGIFY_ENUM_CASE(ELF, SHT_GNU_verdef);
Modified: llvm/trunk/lib/ObjectYAML/ELFYAML.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ObjectYAML/ELFYAML.cpp?rev=333823&r1=333822&r2=333823&view=diff
==============================================================================
--- llvm/trunk/lib/ObjectYAML/ELFYAML.cpp (original)
+++ llvm/trunk/lib/ObjectYAML/ELFYAML.cpp Sat Jun 2 09:33:01 2018
@@ -441,6 +441,7 @@ void ScalarEnumerationTraits<ELFYAML::EL
ECase(SHT_ANDROID_RELA);
ECase(SHT_LLVM_ODRTAB);
ECase(SHT_LLVM_LINKER_OPTIONS);
+ ECase(SHT_LLVM_CALL_GRAPH_PROFILE);
ECase(SHT_GNU_ATTRIBUTES);
ECase(SHT_GNU_HASH);
ECase(SHT_GNU_verdef);
Added: llvm/trunk/test/MC/AsmParser/directive_cgprofile.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/AsmParser/directive_cgprofile.s?rev=333823&view=auto
==============================================================================
--- llvm/trunk/test/MC/AsmParser/directive_cgprofile.s (added)
+++ llvm/trunk/test/MC/AsmParser/directive_cgprofile.s Sat Jun 2 09:33:01 2018
@@ -0,0 +1,9 @@
+# RUN: llvm-mc -triple i386-unknown-unknown %s | FileCheck %s
+
+ .cg_profile a, b, 32
+ .cg_profile freq, a, 11
+ .cg_profile freq, b, 20
+
+# CHECK: .cg_profile a, b, 32
+# CHECK: .cg_profile freq, a, 11
+# CHECK: .cg_profile freq, b, 20
Added: llvm/trunk/test/MC/ELF/cgprofile-error.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/ELF/cgprofile-error.s?rev=333823&view=auto
==============================================================================
--- llvm/trunk/test/MC/ELF/cgprofile-error.s (added)
+++ llvm/trunk/test/MC/ELF/cgprofile-error.s Sat Jun 2 09:33:01 2018
@@ -0,0 +1,7 @@
+# RUN: not llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu %s -o /dev/null 2>&1 | FileCheck %s
+
+ .cg_profile a, .L.temp, 32
+
+# CHECK: cgprofile-error.s:3:18: error: Reference to undefined temporary symbol `.L.temp`
+# CHECK-NEXT: .cg_profile a, .L.temp, 32
+# CHECK-NEXT: ^
Added: llvm/trunk/test/MC/ELF/cgprofile.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/ELF/cgprofile.s?rev=333823&view=auto
==============================================================================
--- llvm/trunk/test/MC/ELF/cgprofile.s (added)
+++ llvm/trunk/test/MC/ELF/cgprofile.s Sat Jun 2 09:33:01 2018
@@ -0,0 +1,100 @@
+# RUN: llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu %s -o - | llvm-readobj -s -t -sd -elf-cg-profile | FileCheck %s
+
+ .section .test,"aw", at progbits
+a: .word b
+
+ .cg_profile a, b, 32
+ .cg_profile freq, a, 11
+ .cg_profile late, late2, 20
+ .cg_profile .L.local, b, 42
+
+ .globl late
+late:
+late2: .word 0
+late3:
+.L.local:
+
+# CHECK: Name: .llvm.call-graph-profile
+# CHECK-NEXT: Type: SHT_LLVM_CALL_GRAPH_PROFILE (0x6FFF4C02)
+# CHECK-NEXT: Flags [ (0x80000000)
+# CHECK-NEXT: SHF_EXCLUDE (0x80000000)
+# CHECK-NEXT: ]
+# CHECK-NEXT: Address:
+# CHECK-NEXT: Offset:
+# CHECK-NEXT: Size: 64
+# CHECK-NEXT: Link: 6
+# CHECK-NEXT: Info: 0
+# CHECK-NEXT: AddressAlignment: 1
+# CHECK-NEXT: EntrySize: 16
+# CHECK-NEXT: SectionData (
+# CHECK-NEXT: 0000: 01000000 05000000 20000000 00000000
+# CHECK-NEXT: 0010: 06000000 01000000 0B000000 00000000
+# CHECK-NEXT: 0020: 07000000 02000000 14000000 00000000
+# CHECK-NEXT: 0030: 04000000 05000000 2A000000 00000000
+# CHECK-NEXT: )
+
+# CHECK: Symbols [
+# CHECK: Name: a
+# CHECK-NEXT: Value:
+# CHECK-NEXT: Size:
+# CHECK-NEXT: Binding: Local
+# CHECK-NEXT: Type:
+# CHECK-NEXT: Other:
+# CHECK-NEXT: Section: .test
+# CHECK: Name: late2
+# CHECK-NEXT: Value:
+# CHECK-NEXT: Size:
+# CHECK-NEXT: Binding: Local
+# CHECK-NEXT: Type:
+# CHECK-NEXT: Other:
+# CHECK-NEXT: Section: .test
+# CHECK: Name: late3
+# CHECK-NEXT: Value:
+# CHECK-NEXT: Size:
+# CHECK-NEXT: Binding: Local
+# CHECK-NEXT: Type:
+# CHECK-NEXT: Other:
+# CHECK-NEXT: Section: .test
+# CHECK: Name: b
+# CHECK-NEXT: Value:
+# CHECK-NEXT: Size:
+# CHECK-NEXT: Binding: Global
+# CHECK-NEXT: Type:
+# CHECK-NEXT: Other:
+# CHECK-NEXT: Section: Undefined
+# CHECK: Name: freq
+# CHECK-NEXT: Value:
+# CHECK-NEXT: Size:
+# CHECK-NEXT: Binding: Weak
+# CHECK-NEXT: Type:
+# CHECK-NEXT: Other:
+# CHECK-NEXT: Section: Undefined
+# CHECK: Name: late
+# CHECK-NEXT: Value:
+# CHECK-NEXT: Size:
+# CHECK-NEXT: Binding: Global
+# CHECK-NEXT: Type:
+# CHECK-NEXT: Other:
+# CHECK-NEXT: Section: .test
+# CHECK: CGProfile [
+# CHECK-NEXT: CGProfileEntry {
+# CHECK-NEXT: From: a
+# CHECK-NEXT: To: b
+# CHECK-NEXT: Weight: 32
+# CHECK-NEXT: }
+# CHECK-NEXT: CGProfileEntry {
+# CHECK-NEXT: From: freq
+# CHECK-NEXT: To: a
+# CHECK-NEXT: Weight: 11
+# CHECK-NEXT: }
+# CHECK-NEXT: CGProfileEntry {
+# CHECK-NEXT: From: late
+# CHECK-NEXT: To: late2
+# CHECK-NEXT: Weight: 20
+# CHECK-NEXT: }
+# CHECK-NEXT: CGProfileEntry {
+# CHECK-NEXT: From:
+# CHECK-NEXT: To: b
+# CHECK-NEXT: Weight: 42
+# CHECK-NEXT: }
+# CHECK-NEXT: ]
\ No newline at end of file
Modified: llvm/trunk/tools/llvm-readobj/ELFDumper.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-readobj/ELFDumper.cpp?rev=333823&r1=333822&r2=333823&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-readobj/ELFDumper.cpp (original)
+++ llvm/trunk/tools/llvm-readobj/ELFDumper.cpp Sat Jun 2 09:33:01 2018
@@ -100,6 +100,7 @@ using namespace ELF;
using Elf_Vernaux = typename ELFT::Vernaux; \
using Elf_Verdef = typename ELFT::Verdef; \
using Elf_Verdaux = typename ELFT::Verdaux; \
+ using Elf_CGProfile = typename ELFT::CGProfile; \
using uintX_t = typename ELFT::uint;
namespace {
@@ -164,6 +165,8 @@ public:
void printHashHistogram() override;
+ void printCGProfile() override;
+
void printNotes() override;
void printELFLinkerOptions() override;
@@ -210,6 +213,7 @@ private:
const Elf_Hash *HashTable = nullptr;
const Elf_GnuHash *GnuHashTable = nullptr;
const Elf_Shdr *DotSymtabSec = nullptr;
+ const Elf_Shdr *DotCGProfileSec = nullptr;
StringRef DynSymtabName;
ArrayRef<Elf_Word> ShndxTable;
@@ -257,9 +261,11 @@ public:
void getSectionNameIndex(const Elf_Sym *Symbol, const Elf_Sym *FirstSym,
StringRef &SectionName,
unsigned &SectionIndex) const;
+ StringRef getStaticSymbolName(uint32_t Index) const;
void printSymbolsHelper(bool IsDynamic) const;
const Elf_Shdr *getDotSymtabSec() const { return DotSymtabSec; }
+ const Elf_Shdr *getDotCGProfileSec() const { return DotCGProfileSec; }
ArrayRef<Elf_Word> getShndxTable() const { return ShndxTable; }
StringRef getDynamicStringTable() const { return DynamicStringTable; }
const DynRegionInfo &getDynRelRegion() const { return DynRelRegion; }
@@ -319,6 +325,7 @@ public:
bool IsDynamic) = 0;
virtual void printProgramHeaders(const ELFFile<ELFT> *Obj) = 0;
virtual void printHashHistogram(const ELFFile<ELFT> *Obj) = 0;
+ virtual void printCGProfile(const ELFFile<ELFT> *Obj) = 0;
virtual void printNotes(const ELFFile<ELFT> *Obj) = 0;
virtual void printELFLinkerOptions(const ELFFile<ELFT> *Obj) = 0;
virtual void printMipsGOT(const MipsGOTParser<ELFT> &Parser) = 0;
@@ -349,6 +356,7 @@ public:
size_t Offset) override;
void printProgramHeaders(const ELFO *Obj) override;
void printHashHistogram(const ELFFile<ELFT> *Obj) override;
+ void printCGProfile(const ELFFile<ELFT> *Obj) override;
void printNotes(const ELFFile<ELFT> *Obj) override;
void printELFLinkerOptions(const ELFFile<ELFT> *Obj) override;
void printMipsGOT(const MipsGOTParser<ELFT> &Parser) override;
@@ -410,6 +418,7 @@ public:
void printDynamicRelocations(const ELFO *Obj) override;
void printProgramHeaders(const ELFO *Obj) override;
void printHashHistogram(const ELFFile<ELFT> *Obj) override;
+ void printCGProfile(const ELFFile<ELFT> *Obj) override;
void printNotes(const ELFFile<ELFT> *Obj) override;
void printELFLinkerOptions(const ELFFile<ELFT> *Obj) override;
void printMipsGOT(const MipsGOTParser<ELFT> &Parser) override;
@@ -737,6 +746,16 @@ StringRef ELFDumper<ELFT>::getSymbolVers
}
template <typename ELFT>
+StringRef ELFDumper<ELFT>::getStaticSymbolName(uint32_t Index) const {
+ StringRef StrTable = unwrapOrError(Obj->getStringTableForSymtab(*DotSymtabSec));
+ Elf_Sym_Range Syms = unwrapOrError(Obj->symbols(DotSymtabSec));
+ if (Index >= Syms.size())
+ reportError("Invalid symbol index");
+ const Elf_Sym *Sym = &Syms[Index];
+ return unwrapOrError(Sym->getName(StrTable));
+}
+
+template <typename ELFT>
std::string ELFDumper<ELFT>::getFullSymbolName(const Elf_Sym *Symbol,
StringRef StrTable,
bool IsDynamic) const {
@@ -1390,6 +1409,10 @@ ELFDumper<ELFT>::ELFDumper(const ELFFile
reportError("Multiple SHT_GNU_verneed");
dot_gnu_version_r_sec = &Sec;
break;
+ case ELF::SHT_LLVM_CALL_GRAPH_PROFILE:
+ if (DotCGProfileSec != nullptr)
+ reportError("Multiple .note.llvm.cgprofile");
+ DotCGProfileSec = &Sec;
}
}
@@ -1534,6 +1557,10 @@ template <class ELFT> void ELFDumper<ELF
ELFDumperStyle->printHashHistogram(Obj);
}
+template <class ELFT> void ELFDumper<ELFT>::printCGProfile() {
+ ELFDumperStyle->printCGProfile(Obj);
+}
+
template <class ELFT> void ELFDumper<ELFT>::printNotes() {
ELFDumperStyle->printNotes(Obj);
}
@@ -2721,6 +2748,8 @@ std::string getSectionTypeString(unsigne
return "LLVM_ODRTAB";
case SHT_LLVM_LINKER_OPTIONS:
return "LLVM_LINKER_OPTIONS";
+ case SHT_LLVM_CALL_GRAPH_PROFILE:
+ return "LLVM_CALL_GRAPH_PROFILE";
// FIXME: Parse processor specific GNU attributes
case SHT_GNU_ATTRIBUTES:
return "ATTRIBUTES";
@@ -3374,6 +3403,11 @@ void GNUStyle<ELFT>::printHashHistogram(
}
}
+template <class ELFT>
+void GNUStyle<ELFT>::printCGProfile(const ELFFile<ELFT> *Obj) {
+ OS << "GNUStyle::printCGProfile not implemented\n";
+}
+
static std::string getGNUNoteTypeName(const uint32_t NT) {
static const struct {
uint32_t ID;
@@ -4138,6 +4172,24 @@ void LLVMStyle<ELFT>::printHashHistogram
}
template <class ELFT>
+void LLVMStyle<ELFT>::printCGProfile(const ELFFile<ELFT> *Obj) {
+ ListScope L(W, "CGProfile");
+ if (!this->dumper()->getDotCGProfileSec())
+ return;
+ auto CGProfile =
+ unwrapOrError(Obj->template getSectionContentsAsArray<Elf_CGProfile>(
+ this->dumper()->getDotCGProfileSec()));
+ for (const Elf_CGProfile &CGPE : CGProfile) {
+ DictScope D(W, "CGProfileEntry");
+ W.printNumber("From", this->dumper()->getStaticSymbolName(CGPE.cgp_from),
+ CGPE.cgp_from);
+ W.printNumber("To", this->dumper()->getStaticSymbolName(CGPE.cgp_to),
+ CGPE.cgp_to);
+ W.printNumber("Weight", CGPE.cgp_weight);
+ }
+}
+
+template <class ELFT>
void LLVMStyle<ELFT>::printNotes(const ELFFile<ELFT> *Obj) {
W.startLine() << "printNotes not implemented!\n";
}
Modified: llvm/trunk/tools/llvm-readobj/ObjDumper.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-readobj/ObjDumper.h?rev=333823&r1=333822&r2=333823&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-readobj/ObjDumper.h (original)
+++ llvm/trunk/tools/llvm-readobj/ObjDumper.h Sat Jun 2 09:33:01 2018
@@ -47,6 +47,7 @@ public:
virtual void printVersionInfo() {}
virtual void printGroupSections() {}
virtual void printHashHistogram() {}
+ virtual void printCGProfile() {}
virtual void printNotes() {}
virtual void printELFLinkerOptions() {}
Modified: llvm/trunk/tools/llvm-readobj/llvm-readobj.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-readobj/llvm-readobj.cpp?rev=333823&r1=333822&r2=333823&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-readobj/llvm-readobj.cpp (original)
+++ llvm/trunk/tools/llvm-readobj/llvm-readobj.cpp Sat Jun 2 09:33:01 2018
@@ -284,6 +284,8 @@ namespace opts {
cl::alias HashHistogramShort("I", cl::desc("Alias for -elf-hash-histogram"),
cl::aliasopt(HashHistogram));
+ cl::opt<bool> CGProfile("elf-cg-profile", cl::desc("Display callgraph profile section"));
+
cl::opt<OutputStyleTy>
Output("elf-output-style", cl::desc("Specify ELF dump style"),
cl::values(clEnumVal(LLVM, "LLVM default style"),
@@ -441,6 +443,8 @@ static void dumpObject(const ObjectFile
Dumper->printGroupSections();
if (opts::HashHistogram)
Dumper->printHashHistogram();
+ if (opts::CGProfile)
+ Dumper->printCGProfile();
if (opts::Notes)
Dumper->printNotes();
}
More information about the llvm-commits
mailing list