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
, llvm::endianness::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
=
44 endian::readNext
<uint64_t, llvm::endianness::little
, unaligned
>(Ptr
);
45 for (uint64_t I
= 0; I
< NumNodes
; I
++) {
46 IndexedAllocationInfo Node
;
47 const uint64_t NumFrames
=
48 endian::readNext
<uint64_t, llvm::endianness::little
, unaligned
>(Ptr
);
49 for (uint64_t J
= 0; J
< NumFrames
; J
++) {
51 endian::readNext
<FrameId
, llvm::endianness::little
, unaligned
>(Ptr
);
52 Node
.CallStack
.push_back(Id
);
54 Node
.Info
.deserialize(Schema
, Ptr
);
55 Ptr
+= PortableMemInfoBlock::serializedSize();
56 Record
.AllocSites
.push_back(Node
);
59 // Read the callsite information.
60 const uint64_t NumCtxs
=
61 endian::readNext
<uint64_t, llvm::endianness::little
, unaligned
>(Ptr
);
62 for (uint64_t J
= 0; J
< NumCtxs
; J
++) {
63 const uint64_t NumFrames
=
64 endian::readNext
<uint64_t, llvm::endianness::little
, unaligned
>(Ptr
);
65 llvm::SmallVector
<FrameId
> Frames
;
66 Frames
.reserve(NumFrames
);
67 for (uint64_t K
= 0; K
< NumFrames
; K
++) {
69 endian::readNext
<FrameId
, llvm::endianness::little
, unaligned
>(Ptr
);
72 Record
.CallSites
.push_back(Frames
);
78 GlobalValue::GUID
IndexedMemProfRecord::getGUID(const StringRef FunctionName
) {
79 // Canonicalize the function name to drop suffixes such as ".llvm.", ".uniq."
80 // etc. We can then match functions in the profile use phase prior to the
81 // addition of these suffixes. Note that this applies to both instrumented and
82 // sampled function names.
83 StringRef CanonicalName
=
84 sampleprof::FunctionSamples::getCanonicalFnName(FunctionName
);
86 // We use the function guid which we expect to be a uint64_t. At
87 // this time, it is the lower 64 bits of the md5 of the canonical
89 return Function::getGUID(CanonicalName
);
92 Expected
<MemProfSchema
> readMemProfSchema(const unsigned char *&Buffer
) {
93 using namespace support
;
95 const unsigned char *Ptr
= Buffer
;
96 const uint64_t NumSchemaIds
=
97 endian::readNext
<uint64_t, llvm::endianness::little
, unaligned
>(Ptr
);
98 if (NumSchemaIds
> static_cast<uint64_t>(Meta::Size
)) {
99 return make_error
<InstrProfError
>(instrprof_error::malformed
,
100 "memprof schema invalid");
103 MemProfSchema Result
;
104 for (size_t I
= 0; I
< NumSchemaIds
; I
++) {
106 endian::readNext
<uint64_t, llvm::endianness::little
, unaligned
>(Ptr
);
107 if (Tag
>= static_cast<uint64_t>(Meta::Size
)) {
108 return make_error
<InstrProfError
>(instrprof_error::malformed
,
109 "memprof schema invalid");
111 Result
.push_back(static_cast<Meta
>(Tag
));
113 // Advace the buffer to one past the schema if we succeeded.
118 } // namespace memprof