[COFF] Add cg_profile directive and .llvm.call-graph-profile section

Subscribers: hiraditya, llvm-commits

Tags: #llvm

Differential Revision: https://reviews.llvm.org/D83597
This commit is contained in:
Zequan Wu 2020-06-25 20:35:03 -07:00
parent 048d5c03ed
commit 3601df5ad2
9 changed files with 228 additions and 40 deletions

View File

@ -98,6 +98,8 @@ public:
return getParser().parseOptionalToken(T);
}
bool ParseDirectiveCGProfile(StringRef, SMLoc);
bool check(bool P, const Twine &Msg) {
return getParser().check(P, Msg);
}

View File

@ -64,6 +64,8 @@ public:
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 @@ protected:
void emitInstToData(const MCInst &Inst, const MCSubtargetInfo &STI) override;
void finalizeCGProfileEntry(const MCSymbolRefExpr *&S);
void finalizeCGProfile();
private:
void Error(const Twine &Msg) const;
};

View File

@ -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) {

View File

@ -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 {

View File

@ -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;
}

View File

@ -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();
}

View File

@ -154,6 +154,8 @@ public:
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

View File

@ -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

119
test/MC/COFF/cgprofile.s Normal file
View File

@ -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: ]