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" 8 9 namespace llvm { 10 namespace memprof { 11 12 void IndexedMemProfRecord::serialize(const MemProfSchema &Schema, 13 raw_ostream &OS) { 14 using namespace support; 15 16 endian::Writer LE(OS, llvm::endianness::little); 17 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); 24 } 25 26 // Related contexts. 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); 32 } 33 } 34 35 IndexedMemProfRecord 36 IndexedMemProfRecord::deserialize(const MemProfSchema &Schema, 37 const unsigned char *Ptr) { 38 using namespace support; 39 40 IndexedMemProfRecord Record; 41 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++) { 50 const FrameId Id = 51 endian::readNext<FrameId, llvm::endianness::little, unaligned>(Ptr); 52 Node.CallStack.push_back(Id); 53 } 54 Node.Info.deserialize(Schema, Ptr); 55 Ptr += PortableMemInfoBlock::serializedSize(); 56 Record.AllocSites.push_back(Node); 57 } 58 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++) { 68 const FrameId Id = 69 endian::readNext<FrameId, llvm::endianness::little, unaligned>(Ptr); 70 Frames.push_back(Id); 71 } 72 Record.CallSites.push_back(Frames); 73 } 74 75 return Record; 76 } 77 78 GlobalValue::GUID IndexedMemProfRecord::getGUID(const StringRef FunctionName) { 79 // Canonicalize the function name to drop suffixes such as ".llvm.". Note 80 // we do not drop any ".__uniq." suffixes, as getCanonicalFnName does not drop 81 // those by default. This is by design to differentiate internal linkage 82 // functions during matching. By dropping the other suffixes we can then match 83 // functions in the profile use phase prior to their addition. Note that this 84 // applies to both instrumented and sampled function names. 85 StringRef CanonicalName = 86 sampleprof::FunctionSamples::getCanonicalFnName(FunctionName); 87 88 // We use the function guid which we expect to be a uint64_t. At 89 // this time, it is the lower 64 bits of the md5 of the canonical 90 // function name. 91 return Function::getGUID(CanonicalName); 92 } 93 94 Expected<MemProfSchema> readMemProfSchema(const unsigned char *&Buffer) { 95 using namespace support; 96 97 const unsigned char *Ptr = Buffer; 98 const uint64_t NumSchemaIds = 99 endian::readNext<uint64_t, llvm::endianness::little, unaligned>(Ptr); 100 if (NumSchemaIds > static_cast<uint64_t>(Meta::Size)) { 101 return make_error<InstrProfError>(instrprof_error::malformed, 102 "memprof schema invalid"); 103 } 104 105 MemProfSchema Result; 106 for (size_t I = 0; I < NumSchemaIds; I++) { 107 const uint64_t Tag = 108 endian::readNext<uint64_t, llvm::endianness::little, unaligned>(Ptr); 109 if (Tag >= static_cast<uint64_t>(Meta::Size)) { 110 return make_error<InstrProfError>(instrprof_error::malformed, 111 "memprof schema invalid"); 112 } 113 Result.push_back(static_cast<Meta>(Tag)); 114 } 115 // Advace the buffer to one past the schema if we succeeded. 116 Buffer = Ptr; 117 return Result; 118 } 119 120 } // namespace memprof 121 } // namespace llvm 122