[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