[llvm] 0f0c5af - [COFF] Add cg_profile directive and .llvm.call-graph-profile section
Zequan Wu via llvm-commits
llvm-commits at lists.llvm.org
Fri Jul 10 17:07:41 PDT 2020
Author: Zequan Wu
Date: 2020-07-10T17:07:30-07:00
New Revision: 0f0c5af3db9b0159d9b1a89faff3bd047510b628
URL: https://github.com/llvm/llvm-project/commit/0f0c5af3db9b0159d9b1a89faff3bd047510b628
DIFF: https://github.com/llvm/llvm-project/commit/0f0c5af3db9b0159d9b1a89faff3bd047510b628.diff
LOG: [COFF] Add cg_profile directive and .llvm.call-graph-profile section
Subscribers: hiraditya, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D83597
Added:
llvm/test/MC/COFF/cgprofile.s
Modified:
llvm/include/llvm/MC/MCParser/MCAsmParserExtension.h
llvm/include/llvm/MC/MCWinCOFFStreamer.h
llvm/lib/MC/MCParser/COFFAsmParser.cpp
llvm/lib/MC/MCParser/ELFAsmParser.cpp
llvm/lib/MC/MCParser/MCAsmParserExtension.cpp
llvm/lib/MC/MCWinCOFFStreamer.cpp
llvm/lib/MC/WinCOFFObjectWriter.cpp
llvm/test/MC/AsmParser/directive_cgprofile.s
Removed:
################################################################################
diff --git a/llvm/include/llvm/MC/MCParser/MCAsmParserExtension.h b/llvm/include/llvm/MC/MCParser/MCAsmParserExtension.h
index 5d2afe81a54b..c37889cfc509 100644
--- a/llvm/include/llvm/MC/MCParser/MCAsmParserExtension.h
+++ b/llvm/include/llvm/MC/MCParser/MCAsmParserExtension.h
@@ -98,6 +98,8 @@ class MCAsmParserExtension {
return getParser().parseOptionalToken(T);
}
+ bool ParseDirectiveCGProfile(StringRef, SMLoc);
+
bool check(bool P, const Twine &Msg) {
return getParser().check(P, Msg);
}
diff --git a/llvm/include/llvm/MC/MCWinCOFFStreamer.h b/llvm/include/llvm/MC/MCWinCOFFStreamer.h
index b5f570ec335c..1236304b9e5d 100644
--- a/llvm/include/llvm/MC/MCWinCOFFStreamer.h
+++ b/llvm/include/llvm/MC/MCWinCOFFStreamer.h
@@ -64,6 +64,8 @@ class MCWinCOFFStreamer : public MCObjectStreamer {
unsigned ByteAlignment) override;
void emitIdent(StringRef IdentString) override;
void EmitWinEHHandlerData(SMLoc Loc) override;
+ void emitCGProfileEntry(const MCSymbolRefExpr *From,
+ const MCSymbolRefExpr *To, uint64_t Count) override;
void finishImpl() override;
/// \}
@@ -73,6 +75,9 @@ class MCWinCOFFStreamer : public MCObjectStreamer {
void emitInstToData(const MCInst &Inst, const MCSubtargetInfo &STI) override;
+ void finalizeCGProfileEntry(const MCSymbolRefExpr *&S);
+ void finalizeCGProfile();
+
private:
void Error(const Twine &Msg) const;
};
diff --git a/llvm/lib/MC/MCParser/COFFAsmParser.cpp b/llvm/lib/MC/MCParser/COFFAsmParser.cpp
index dec004eb6f95..2104fb83b309 100644
--- a/llvm/lib/MC/MCParser/COFFAsmParser.cpp
+++ b/llvm/lib/MC/MCParser/COFFAsmParser.cpp
@@ -70,6 +70,7 @@ class COFFAsmParser : public MCAsmParserExtension {
addDirectiveHandler<&COFFAsmParser::ParseDirectiveLinkOnce>(".linkonce");
addDirectiveHandler<&COFFAsmParser::ParseDirectiveRVA>(".rva");
addDirectiveHandler<&COFFAsmParser::ParseDirectiveSymbolAttribute>(".weak");
+ addDirectiveHandler<&COFFAsmParser::ParseDirectiveCGProfile>(".cg_profile");
// Win64 EH directives.
addDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveStartProc>(
@@ -125,6 +126,7 @@ class COFFAsmParser : public MCAsmParserExtension {
bool parseCOMDATType(COFF::COMDATType &Type);
bool ParseDirectiveLinkOnce(StringRef, SMLoc);
bool ParseDirectiveRVA(StringRef, SMLoc);
+ bool ParseDirectiveCGProfile(StringRef, SMLoc);
// Win64 EH directives.
bool ParseSEHDirectiveStartProc(StringRef, SMLoc);
@@ -299,6 +301,10 @@ bool COFFAsmParser::ParseDirectiveSymbolAttribute(StringRef Directive, SMLoc) {
return false;
}
+bool COFFAsmParser::ParseDirectiveCGProfile(StringRef S, SMLoc Loc) {
+ return MCAsmParserExtension::ParseDirectiveCGProfile(S, Loc);
+}
+
bool COFFAsmParser::ParseSectionSwitch(StringRef Section,
unsigned Characteristics,
SectionKind Kind) {
diff --git a/llvm/lib/MC/MCParser/ELFAsmParser.cpp b/llvm/lib/MC/MCParser/ELFAsmParser.cpp
index a80e8a5832ef..e5ab13bc719d 100644
--- a/llvm/lib/MC/MCParser/ELFAsmParser.cpp
+++ b/llvm/lib/MC/MCParser/ELFAsmParser.cpp
@@ -862,45 +862,8 @@ bool ELFAsmParser::ParseDirectiveSubsection(StringRef, SMLoc) {
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;
+bool ELFAsmParser::ParseDirectiveCGProfile(StringRef S, SMLoc Loc) {
+ return MCAsmParserExtension::ParseDirectiveCGProfile(S, Loc);
}
namespace llvm {
diff --git a/llvm/lib/MC/MCParser/MCAsmParserExtension.cpp b/llvm/lib/MC/MCParser/MCAsmParserExtension.cpp
index 18d18f0cf6ed..0b5046cd8fad 100644
--- a/llvm/lib/MC/MCParser/MCAsmParserExtension.cpp
+++ b/llvm/lib/MC/MCParser/MCAsmParserExtension.cpp
@@ -7,6 +7,8 @@
//===----------------------------------------------------------------------===//
#include "llvm/MC/MCParser/MCAsmParserExtension.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCStreamer.h"
using namespace llvm;
@@ -17,3 +19,44 @@ MCAsmParserExtension::~MCAsmParserExtension() = default;
void MCAsmParserExtension::Initialize(MCAsmParser &Parser) {
this->Parser = &Parser;
}
+
+/// ParseDirectiveCGProfile
+/// ::= .cg_profile identifier, identifier, <number>
+bool MCAsmParserExtension::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;
+}
diff --git a/llvm/lib/MC/MCWinCOFFStreamer.cpp b/llvm/lib/MC/MCWinCOFFStreamer.cpp
index 7f0f7fccd542..d8fde4004d44 100644
--- a/llvm/lib/MC/MCWinCOFFStreamer.cpp
+++ b/llvm/lib/MC/MCWinCOFFStreamer.cpp
@@ -328,7 +328,34 @@ void MCWinCOFFStreamer::EmitWinEHHandlerData(SMLoc Loc) {
llvm_unreachable("not implemented");
}
+void MCWinCOFFStreamer::emitCGProfileEntry(const MCSymbolRefExpr *From,
+ const MCSymbolRefExpr *To,
+ uint64_t Count) {
+ // Ignore temporary symbols for now.
+ if (!From->getSymbol().isTemporary() && !To->getSymbol().isTemporary())
+ getAssembler().CGProfile.push_back({From, To, Count});
+}
+
+void MCWinCOFFStreamer::finalizeCGProfileEntry(const MCSymbolRefExpr *&SRE) {
+ const MCSymbol *S = &SRE->getSymbol();
+ bool Created;
+ getAssembler().registerSymbol(*S, &Created);
+ if (Created) {
+ cast<MCSymbolCOFF>(S)->setIsWeakExternal();
+ cast<MCSymbolCOFF>(S)->setExternal(true);
+ }
+}
+
+void MCWinCOFFStreamer::finalizeCGProfile() {
+ for (MCAssembler::CGProfileEntry &E : getAssembler().CGProfile) {
+ finalizeCGProfileEntry(E.From);
+ finalizeCGProfileEntry(E.To);
+ }
+}
+
void MCWinCOFFStreamer::finishImpl() {
+ finalizeCGProfile();
+
MCObjectStreamer::finishImpl();
}
diff --git a/llvm/lib/MC/WinCOFFObjectWriter.cpp b/llvm/lib/MC/WinCOFFObjectWriter.cpp
index c6829f5e107a..94a8d56c55fc 100644
--- a/llvm/lib/MC/WinCOFFObjectWriter.cpp
+++ b/llvm/lib/MC/WinCOFFObjectWriter.cpp
@@ -154,6 +154,8 @@ class WinCOFFObjectWriter : public MCObjectWriter {
MCSectionCOFF *AddrsigSection;
std::vector<const MCSymbol *> AddrsigSyms;
+ MCSectionCOFF *CGProfileSection = nullptr;
+
WinCOFFObjectWriter(std::unique_ptr<MCWinCOFFObjectTargetWriter> MOTW,
raw_pwrite_stream &OS);
@@ -674,6 +676,13 @@ void WinCOFFObjectWriter::executePostLayoutBinding(MCAssembler &Asm,
Asm.registerSection(*AddrsigSection);
}
+ if (!Asm.CGProfile.empty()) {
+ CGProfileSection = Asm.getContext().getCOFFSection(
+ ".llvm.call-graph-profile", COFF::IMAGE_SCN_LNK_REMOVE,
+ SectionKind::getMetadata());
+ Asm.registerSection(*CGProfileSection);
+ }
+
// "Define" each section & symbol. This creates section & symbol
// entries in the staging area.
for (const auto &Section : Asm)
@@ -1099,6 +1108,20 @@ uint64_t WinCOFFObjectWriter::writeObject(MCAssembler &Asm,
}
}
+ // Create the contents of the .llvm.call-graph-profile section.
+ if (CGProfileSection) {
+ auto *Frag = new MCDataFragment(CGProfileSection);
+ Frag->setLayoutOrder(0);
+ raw_svector_ostream OS(Frag->getContents());
+ for (const MCAssembler::CGProfileEntry &CGPE : Asm.CGProfile) {
+ uint32_t FromIndex = CGPE.From->getSymbol().getIndex();
+ uint32_t ToIndex = CGPE.To->getSymbol().getIndex();
+ OS.write((const char *)&FromIndex, sizeof(uint32_t));
+ OS.write((const char *)&ToIndex, sizeof(uint32_t));
+ OS.write((const char *)&CGPE.Count, sizeof(uint64_t));
+ }
+ }
+
assignFileOffsets(Asm, Layout);
// MS LINK expects to be able to use this timestamp to implement their
diff --git a/llvm/test/MC/AsmParser/directive_cgprofile.s b/llvm/test/MC/AsmParser/directive_cgprofile.s
index 1db93dcbb033..b7bb82ed270d 100644
--- a/llvm/test/MC/AsmParser/directive_cgprofile.s
+++ b/llvm/test/MC/AsmParser/directive_cgprofile.s
@@ -1,5 +1,5 @@
# RUN: llvm-mc -triple i386-unknown-unknown %s | FileCheck %s
-
+# RUN: llvm-mc -triple x86_64-pc-win32 %s | FileCheck %s
.cg_profile a, b, 32
.cg_profile freq, a, 11
.cg_profile freq, b, 20
diff --git a/llvm/test/MC/COFF/cgprofile.s b/llvm/test/MC/COFF/cgprofile.s
new file mode 100644
index 000000000000..a0c47a69c069
--- /dev/null
+++ b/llvm/test/MC/COFF/cgprofile.s
@@ -0,0 +1,119 @@
+# RUN: llvm-mc -filetype=obj -triple x86_64-pc-win32 %s -o %t
+# RUN: llvm-readobj -S --symbols --sd --cg-profile %t | FileCheck %s
+
+ .section .test,"w"
+a:
+
+ .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: VirtualSize:
+# CHECK-NEXT: VirtualAddress:
+# CHECK-NEXT: RawDataSize: 48
+# CHECK-NEXT: PointerToRawData:
+# CHECK-NEXT: PointerToRelocations:
+# CHECK-NEXT: PointerToLineNumbers:
+# CHECK-NEXT: RelocationCount:
+# CHECK-NEXT: LineNumberCount:
+# CHECK-NEXT: Characteristics [ (0x100800)
+# CHECK-NEXT: IMAGE_SCN_ALIGN_1BYTES (0x100000)
+# CHECK-NEXT: IMAGE_SCN_LNK_REMOVE (0x800)
+# CHECK-NEXT: ]
+# CHECK-NEXT: SectionData (
+# CHECK-NEXT: 0000: 0A000000 0E000000 20000000 00000000
+# CHECK-NEXT: 0010: 11000000 0A000000 0B000000 00000000
+# CHECK-NEXT: 0020: 0B000000 0C000000 14000000 00000000
+# CHECK-NEXT: )
+
+# CHECK: Symbols [
+# CHECK: Name: a
+# CHECK-NEXT: Value:
+# CHECK-NEXT: Section: .test
+# CHECK-NEXT: BaseType:
+# CHECK-NEXT: ComplexType:
+# CHECK-NEXT: StorageClass: Static
+# CHECK-NEXT: AuxSymbolCount:
+# CHECK: Name: late
+# CHECK-NEXT: Value:
+# CHECK-NEXT: Section: .test
+# CHECK-NEXT: BaseType:
+# CHECK-NEXT: ComplexType:
+# CHECK-NEXT: StorageClass: External
+# CHECK-NEXT: AuxSymbolCount:
+# CHECK: Name: late2
+# CHECK-NEXT: Value:
+# CHECK-NEXT: Section: .test
+# CHECK-NEXT: BaseType:
+# CHECK-NEXT: ComplexType:
+# CHECK-NEXT: StorageClass: Static
+# CHECK-NEXT: AuxSymbolCount:
+# CHECK: Name: late3
+# CHECK-NEXT: Value:
+# CHECK-NEXT: Section: .test
+# CHECK-NEXT: BaseType:
+# CHECK-NEXT: ComplexType:
+# CHECK-NEXT: StorageClass: Static
+# CHECK-NEXT: AuxSymbolCount:
+# CHECK: Name: b
+# CHECK-NEXT: Value:
+# CHECK-NEXT: Section: IMAGE_SYM_UNDEFINED
+# CHECK-NEXT: BaseType:
+# CHECK-NEXT: ComplexType:
+# CHECK-NEXT: StorageClass: WeakExternal
+# CHECK-NEXT: AuxSymbolCount: 1
+# CHECK-NEXT: AuxWeakExternal {
+# CHECK-NEXT: Linked: .weak.b.default.late
+# CHECK-NEXT: Search: Alias
+# CHECK-NEXT: }
+# CHECK: Name: .weak.b.default.late
+# CHECK-NEXT: Value:
+# CHECK-NEXT: Section: IMAGE_SYM_ABSOLUTE
+# CHECK-NEXT: BaseType:
+# CHECK-NEXT: ComplexType:
+# CHECK-NEXT: StorageClass: External
+# CHECK-NEXT: AuxSymbolCount: 0
+# CHECK: Name: freq
+# CHECK-NEXT: Value:
+# CHECK-NEXT: Section: IMAGE_SYM_UNDEFINED
+# CHECK-NEXT: BaseType:
+# CHECK-NEXT: ComplexType:
+# CHECK-NEXT: StorageClass: WeakExternal
+# CHECK-NEXT: AuxSymbolCount: 1
+# CHECK-NEXT: AuxWeakExternal {
+# CHECK-NEXT: Linked: .weak.freq.default.late
+# CHECK-NEXT: Search: Alias
+# CHECK-NEXT: }
+# CHECK: Name: .weak.freq.default.late
+# CHECK-NEXT: Value:
+# CHECK-NEXT: Section: IMAGE_SYM_ABSOLUTE
+# CHECK-NEXT: BaseType:
+# CHECK-NEXT: ComplexType:
+# CHECK-NEXT: StorageClass: External
+# CHECK-NEXT: AuxSymbolCount: 0
+
+# 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: ]
More information about the llvm-commits
mailing list