10a418490SSnehasish Kumar #include "llvm/ProfileData/MemProf.h"
227a4f254SSnehasish Kumar #include "llvm/ADT/SmallVector.h"
327a4f254SSnehasish Kumar #include "llvm/IR/Function.h"
4fc97efa4Sserge-sans-paille #include "llvm/ProfileData/InstrProf.h"
50a418490SSnehasish Kumar #include "llvm/Support/Endian.h"
60a418490SSnehasish Kumar #include "llvm/Support/EndianStream.h"
70a418490SSnehasish Kumar 
80a418490SSnehasish Kumar namespace llvm {
90a418490SSnehasish Kumar namespace memprof {
100a418490SSnehasish Kumar 
serialize(const MemProfSchema & Schema,raw_ostream & OS)11*6dd6a616SSnehasish Kumar void IndexedMemProfRecord::serialize(const MemProfSchema &Schema,
12*6dd6a616SSnehasish Kumar                                      raw_ostream &OS) {
130a418490SSnehasish Kumar   using namespace support;
140a418490SSnehasish Kumar 
150a418490SSnehasish Kumar   endian::Writer LE(OS, little);
160a418490SSnehasish Kumar 
1727a4f254SSnehasish Kumar   LE.write<uint64_t>(AllocSites.size());
18*6dd6a616SSnehasish Kumar   for (const IndexedAllocationInfo &N : AllocSites) {
1927a4f254SSnehasish Kumar     LE.write<uint64_t>(N.CallStack.size());
20*6dd6a616SSnehasish Kumar     for (const FrameId &Id : N.CallStack)
21*6dd6a616SSnehasish Kumar       LE.write<FrameId>(Id);
2227a4f254SSnehasish Kumar     N.Info.serialize(Schema, OS);
230a418490SSnehasish Kumar   }
2427a4f254SSnehasish Kumar 
2527a4f254SSnehasish Kumar   // Related contexts.
2627a4f254SSnehasish Kumar   LE.write<uint64_t>(CallSites.size());
2727a4f254SSnehasish Kumar   for (const auto &Frames : CallSites) {
2827a4f254SSnehasish Kumar     LE.write<uint64_t>(Frames.size());
29*6dd6a616SSnehasish Kumar     for (const FrameId &Id : Frames)
30*6dd6a616SSnehasish Kumar       LE.write<FrameId>(Id);
310a418490SSnehasish Kumar   }
320a418490SSnehasish Kumar }
330a418490SSnehasish Kumar 
34*6dd6a616SSnehasish Kumar IndexedMemProfRecord
deserialize(const MemProfSchema & Schema,const unsigned char * Ptr)35*6dd6a616SSnehasish Kumar IndexedMemProfRecord::deserialize(const MemProfSchema &Schema,
360a418490SSnehasish Kumar                                   const unsigned char *Ptr) {
370a418490SSnehasish Kumar   using namespace support;
380a418490SSnehasish Kumar 
39*6dd6a616SSnehasish Kumar   IndexedMemProfRecord Record;
4027a4f254SSnehasish Kumar 
4127a4f254SSnehasish Kumar   // Read the meminfo nodes.
4227a4f254SSnehasish Kumar   const uint64_t NumNodes = endian::readNext<uint64_t, little, unaligned>(Ptr);
4327a4f254SSnehasish Kumar   for (uint64_t I = 0; I < NumNodes; I++) {
44*6dd6a616SSnehasish Kumar     IndexedAllocationInfo Node;
450a418490SSnehasish Kumar     const uint64_t NumFrames =
460a418490SSnehasish Kumar         endian::readNext<uint64_t, little, unaligned>(Ptr);
470a418490SSnehasish Kumar     for (uint64_t J = 0; J < NumFrames; J++) {
48*6dd6a616SSnehasish Kumar       const FrameId Id = endian::readNext<FrameId, little, unaligned>(Ptr);
49*6dd6a616SSnehasish Kumar       Node.CallStack.push_back(Id);
500a418490SSnehasish Kumar     }
5127a4f254SSnehasish Kumar     Node.Info.deserialize(Schema, Ptr);
520a418490SSnehasish Kumar     Ptr += PortableMemInfoBlock::serializedSize();
5327a4f254SSnehasish Kumar     Record.AllocSites.push_back(Node);
540a418490SSnehasish Kumar   }
5527a4f254SSnehasish Kumar 
5627a4f254SSnehasish Kumar   // Read the callsite information.
5727a4f254SSnehasish Kumar   const uint64_t NumCtxs = endian::readNext<uint64_t, little, unaligned>(Ptr);
5827a4f254SSnehasish Kumar   for (uint64_t J = 0; J < NumCtxs; J++) {
5927a4f254SSnehasish Kumar     const uint64_t NumFrames =
6027a4f254SSnehasish Kumar         endian::readNext<uint64_t, little, unaligned>(Ptr);
61*6dd6a616SSnehasish Kumar     llvm::SmallVector<FrameId> Frames;
62*6dd6a616SSnehasish Kumar     Frames.reserve(NumFrames);
6327a4f254SSnehasish Kumar     for (uint64_t K = 0; K < NumFrames; K++) {
64*6dd6a616SSnehasish Kumar       const FrameId Id = endian::readNext<FrameId, little, unaligned>(Ptr);
65*6dd6a616SSnehasish Kumar       Frames.push_back(Id);
6627a4f254SSnehasish Kumar     }
6727a4f254SSnehasish Kumar     Record.CallSites.push_back(Frames);
6827a4f254SSnehasish Kumar   }
6927a4f254SSnehasish Kumar 
7027a4f254SSnehasish Kumar   return Record;
7127a4f254SSnehasish Kumar }
7227a4f254SSnehasish Kumar 
getGUID(const StringRef FunctionName)73*6dd6a616SSnehasish Kumar GlobalValue::GUID IndexedMemProfRecord::getGUID(const StringRef FunctionName) {
7427a4f254SSnehasish Kumar   const auto Pos = FunctionName.find(".llvm.");
7527a4f254SSnehasish Kumar 
7627a4f254SSnehasish Kumar   // We use the function guid which we expect to be a uint64_t. At
7727a4f254SSnehasish Kumar   // this time, it is the lower 64 bits of the md5 of the function
7827a4f254SSnehasish Kumar   // name. Any suffix with .llvm. is trimmed since these are added by
7927a4f254SSnehasish Kumar   // thinLTO global promotion. At the time the profile is consumed,
8027a4f254SSnehasish Kumar   // these suffixes will not be present.
8127a4f254SSnehasish Kumar   return Function::getGUID(FunctionName.take_front(Pos));
820a418490SSnehasish Kumar }
830a418490SSnehasish Kumar 
readMemProfSchema(const unsigned char * & Buffer)840a418490SSnehasish Kumar Expected<MemProfSchema> readMemProfSchema(const unsigned char *&Buffer) {
850a418490SSnehasish Kumar   using namespace support;
860a418490SSnehasish Kumar 
870a418490SSnehasish Kumar   const unsigned char *Ptr = Buffer;
880a418490SSnehasish Kumar   const uint64_t NumSchemaIds =
890a418490SSnehasish Kumar       endian::readNext<uint64_t, little, unaligned>(Ptr);
900a418490SSnehasish Kumar   if (NumSchemaIds > static_cast<uint64_t>(Meta::Size)) {
910a418490SSnehasish Kumar     return make_error<InstrProfError>(instrprof_error::malformed,
920a418490SSnehasish Kumar                                       "memprof schema invalid");
930a418490SSnehasish Kumar   }
940a418490SSnehasish Kumar 
950a418490SSnehasish Kumar   MemProfSchema Result;
960a418490SSnehasish Kumar   for (size_t I = 0; I < NumSchemaIds; I++) {
970a418490SSnehasish Kumar     const uint64_t Tag = endian::readNext<uint64_t, little, unaligned>(Ptr);
980a418490SSnehasish Kumar     if (Tag >= static_cast<uint64_t>(Meta::Size)) {
990a418490SSnehasish Kumar       return make_error<InstrProfError>(instrprof_error::malformed,
1000a418490SSnehasish Kumar                                         "memprof schema invalid");
1010a418490SSnehasish Kumar     }
1020a418490SSnehasish Kumar     Result.push_back(static_cast<Meta>(Tag));
1030a418490SSnehasish Kumar   }
1040a418490SSnehasish Kumar   // Advace the buffer to one past the schema if we succeeded.
1050a418490SSnehasish Kumar   Buffer = Ptr;
1060a418490SSnehasish Kumar   return Result;
1070a418490SSnehasish Kumar }
1080a418490SSnehasish Kumar 
1090a418490SSnehasish Kumar } // namespace memprof
1100a418490SSnehasish Kumar } // namespace llvm
111