1 #include "llvm/ProfileData/MemProf.h"
2 #include "llvm/ProfileData/InstrProf.h"
3 #include "llvm/Support/Endian.h"
4 #include "llvm/Support/EndianStream.h"
5 
6 namespace llvm {
7 namespace memprof {
8 
9 void serializeRecords(const ArrayRef<MemProfRecord> Records,
10                       const MemProfSchema &Schema, raw_ostream &OS) {
11   using namespace support;
12 
13   endian::Writer LE(OS, little);
14 
15   LE.write<uint64_t>(Records.size());
16   for (const MemProfRecord &MR : Records) {
17     LE.write<uint64_t>(MR.CallStack.size());
18     for (const MemProfRecord::Frame &F : MR.CallStack) {
19       F.serialize(OS);
20     }
21     MR.Info.serialize(Schema, OS);
22   }
23 }
24 
25 SmallVector<MemProfRecord, 4> deserializeRecords(const MemProfSchema &Schema,
26                                                  const unsigned char *Ptr) {
27   using namespace support;
28 
29   SmallVector<MemProfRecord, 4> Records;
30   const uint64_t NumRecords =
31       endian::readNext<uint64_t, little, unaligned>(Ptr);
32   for (uint64_t I = 0; I < NumRecords; I++) {
33     MemProfRecord MR;
34     const uint64_t NumFrames =
35         endian::readNext<uint64_t, little, unaligned>(Ptr);
36     for (uint64_t J = 0; J < NumFrames; J++) {
37       const auto F = MemProfRecord::Frame::deserialize(Ptr);
38       Ptr += MemProfRecord::Frame::serializedSize();
39       MR.CallStack.push_back(F);
40     }
41     MR.Info.deserialize(Schema, Ptr);
42     Ptr += PortableMemInfoBlock::serializedSize();
43     Records.push_back(MR);
44   }
45   return Records;
46 }
47 
48 Expected<MemProfSchema> readMemProfSchema(const unsigned char *&Buffer) {
49   using namespace support;
50 
51   const unsigned char *Ptr = Buffer;
52   const uint64_t NumSchemaIds =
53       endian::readNext<uint64_t, little, unaligned>(Ptr);
54   if (NumSchemaIds > static_cast<uint64_t>(Meta::Size)) {
55     return make_error<InstrProfError>(instrprof_error::malformed,
56                                       "memprof schema invalid");
57   }
58 
59   MemProfSchema Result;
60   for (size_t I = 0; I < NumSchemaIds; I++) {
61     const uint64_t Tag = endian::readNext<uint64_t, little, unaligned>(Ptr);
62     if (Tag >= static_cast<uint64_t>(Meta::Size)) {
63       return make_error<InstrProfError>(instrprof_error::malformed,
64                                         "memprof schema invalid");
65     }
66     Result.push_back(static_cast<Meta>(Tag));
67   }
68   // Advace the buffer to one past the schema if we succeeded.
69   Buffer = Ptr;
70   return Result;
71 }
72 
73 } // namespace memprof
74 } // namespace llvm
75