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