mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-28 13:51:09 +00:00
[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:
parent
048d5c03ed
commit
3601df5ad2
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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) {
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
119
test/MC/COFF/cgprofile.s
Normal 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: ]
|
Loading…
Reference in New Issue
Block a user