1 #include "llvm/ProfileData/MemProf.h"
2 #include "llvm/ADT/SmallVector.h"
3 #include "llvm/IR/Function.h"
4 #include "llvm/ProfileData/InstrProf.h"
5 #include "llvm/ProfileData/SampleProf.h"
6 #include "llvm/Support/Endian.h"
7 #include "llvm/Support/EndianStream.h"
12 void IndexedMemProfRecord::serialize(const MemProfSchema
&Schema
,
14 using namespace support
;
16 endian::Writer
LE(OS
, little
);
18 LE
.write
<uint64_t>(AllocSites
.size());
19 for (const IndexedAllocationInfo
&N
: AllocSites
) {
20 LE
.write
<uint64_t>(N
.CallStack
.size());
21 for (const FrameId
&Id
: N
.CallStack
)
22 LE
.write
<FrameId
>(Id
);
23 N
.Info
.serialize(Schema
, OS
);
27 LE
.write
<uint64_t>(CallSites
.size());
28 for (const auto &Frames
: CallSites
) {
29 LE
.write
<uint64_t>(Frames
.size());
30 for (const FrameId
&Id
: Frames
)
31 LE
.write
<FrameId
>(Id
);
36 IndexedMemProfRecord::deserialize(const MemProfSchema
&Schema
,
37 const unsigned char *Ptr
) {
38 using namespace support
;
40 IndexedMemProfRecord Record
;
42 // Read the meminfo nodes.
43 const uint64_t NumNodes
= endian::readNext
<uint64_t, little
, unaligned
>(Ptr
);
44 for (uint64_t I
= 0; I
< NumNodes
; I
++) {
45 IndexedAllocationInfo Node
;
46 const uint64_t NumFrames
=
47 endian::readNext
<uint64_t, little
, unaligned
>(Ptr
);
48 for (uint64_t J
= 0; J
< NumFrames
; J
++) {
49 const FrameId Id
= endian::readNext
<FrameId
, little
, unaligned
>(Ptr
);
50 Node
.CallStack
.push_back(Id
);
52 Node
.Info
.deserialize(Schema
, Ptr
);
53 Ptr
+= PortableMemInfoBlock::serializedSize();
54 Record
.AllocSites
.push_back(Node
);
57 // Read the callsite information.
58 const uint64_t NumCtxs
= endian::readNext
<uint64_t, little
, unaligned
>(Ptr
);
59 for (uint64_t J
= 0; J
< NumCtxs
; J
++) {
60 const uint64_t NumFrames
=
61 endian::readNext
<uint64_t, little
, unaligned
>(Ptr
);
62 llvm::SmallVector
<FrameId
> Frames
;
63 Frames
.reserve(NumFrames
);
64 for (uint64_t K
= 0; K
< NumFrames
; K
++) {
65 const FrameId Id
= endian::readNext
<FrameId
, little
, unaligned
>(Ptr
);
68 Record
.CallSites
.push_back(Frames
);
74 GlobalValue::GUID
IndexedMemProfRecord::getGUID(const StringRef FunctionName
) {
75 // Canonicalize the function name to drop suffixes such as ".llvm.", ".uniq."
76 // etc. We can then match functions in the profile use phase prior to the
77 // addition of these suffixes. Note that this applies to both instrumented and
78 // sampled function names.
79 StringRef CanonicalName
=
80 sampleprof::FunctionSamples::getCanonicalFnName(FunctionName
);
82 // We use the function guid which we expect to be a uint64_t. At
83 // this time, it is the lower 64 bits of the md5 of the canonical
85 return Function::getGUID(CanonicalName
);
88 Expected
<MemProfSchema
> readMemProfSchema(const unsigned char *&Buffer
) {
89 using namespace support
;
91 const unsigned char *Ptr
= Buffer
;
92 const uint64_t NumSchemaIds
=
93 endian::readNext
<uint64_t, little
, unaligned
>(Ptr
);
94 if (NumSchemaIds
> static_cast<uint64_t>(Meta::Size
)) {
95 return make_error
<InstrProfError
>(instrprof_error::malformed
,
96 "memprof schema invalid");
100 for (size_t I
= 0; I
< NumSchemaIds
; I
++) {
101 const uint64_t Tag
= endian::readNext
<uint64_t, little
, unaligned
>(Ptr
);
102 if (Tag
>= static_cast<uint64_t>(Meta::Size
)) {
103 return make_error
<InstrProfError
>(instrprof_error::malformed
,
104 "memprof schema invalid");
106 Result
.push_back(static_cast<Meta
>(Tag
));
108 // Advace the buffer to one past the schema if we succeeded.
113 } // namespace memprof