//===- ProfileDataLoader.cpp - Load profile information from disk ---------===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // The ProfileDataLoader class is used to load raw profiling data from the dump // file. // //===----------------------------------------------------------------------===// #include "llvm/Analysis/ProfileDataLoader.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/OwningPtr.h" #include "llvm/Analysis/ProfileDataTypes.h" #include "llvm/IR/InstrTypes.h" #include "llvm/IR/Module.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Support/system_error.h" #include #include using namespace llvm; raw_ostream &llvm::operator<<(raw_ostream &O, std::pair E) { O << "("; if (E.first) O << E.first->getName(); else O << "0"; O << ","; if (E.second) O << E.second->getName(); else O << "0"; return O << ")"; } /// AddCounts - Add 'A' and 'B', accounting for the fact that the value of one /// (or both) may not be defined. static unsigned AddCounts(unsigned A, unsigned B) { // If either value is undefined, use the other. // Undefined + undefined = undefined. if (A == ProfileDataLoader::Uncounted) return B; if (B == ProfileDataLoader::Uncounted) return A; return A + B; } /// ReadProfilingData - Load 'NumEntries' items of type 'T' from file 'F' template static void ReadProfilingData(const char *ToolName, FILE *F, T *Data, size_t NumEntries) { // Read in the block of data... if (fread(Data, sizeof(T), NumEntries, F) != NumEntries) report_fatal_error(Twine(ToolName) + ": Profiling data truncated"); } /// ReadProfilingNumEntries - Read how many entries are in this profiling data /// packet. static unsigned ReadProfilingNumEntries(const char *ToolName, FILE *F, bool ShouldByteSwap) { unsigned Entry; ReadProfilingData(ToolName, F, &Entry, 1); return ShouldByteSwap ? ByteSwap_32(Entry) : Entry; } /// ReadProfilingBlock - Read the number of entries in the next profiling data /// packet and then accumulate the entries into 'Data'. static void ReadProfilingBlock(const char *ToolName, FILE *F, bool ShouldByteSwap, SmallVector &Data) { // Read the number of entries... unsigned NumEntries = ReadProfilingNumEntries(ToolName, F, ShouldByteSwap); // Read in the data. SmallVector TempSpace(NumEntries); ReadProfilingData(ToolName, F, TempSpace.data(), NumEntries); // Make sure we have enough space ... if (Data.size() < NumEntries) Data.resize(NumEntries, ProfileDataLoader::Uncounted); // Accumulate the data we just read into the existing data. for (unsigned i = 0; i < NumEntries; ++i) { unsigned Entry = ShouldByteSwap ? ByteSwap_32(TempSpace[i]) : TempSpace[i]; Data[i] = AddCounts(Entry, Data[i]); } } /// ReadProfilingArgBlock - Read the command line arguments that the progam was /// run with when the current profiling data packet(s) were generated. static void ReadProfilingArgBlock(const char *ToolName, FILE *F, bool ShouldByteSwap, SmallVector &CommandLines) { // Read the number of bytes ... unsigned ArgLength = ReadProfilingNumEntries(ToolName, F, ShouldByteSwap); // Read in the arguments (if there are any to read). Round up the length to // the nearest 4-byte multiple. SmallVector Args(ArgLength+4); if (ArgLength) ReadProfilingData(ToolName, F, Args.data(), (ArgLength+3) & ~3); // Store the arguments. CommandLines.push_back(std::string(&Args[0], &Args[ArgLength])); } const unsigned ProfileDataLoader::Uncounted = ~0U; /// ProfileDataLoader ctor - Read the specified profiling data file, reporting /// a fatal error if the file is invalid or broken. ProfileDataLoader::ProfileDataLoader(const char *ToolName, const std::string &Filename) : Filename(Filename) { FILE *F = fopen(Filename.c_str(), "rb"); if (F == 0) report_fatal_error(Twine(ToolName) + ": Error opening '" + Filename + "': "); // Keep reading packets until we run out of them. unsigned PacketType; while (fread(&PacketType, sizeof(unsigned), 1, F) == 1) { // If the low eight bits of the packet are zero, we must be dealing with an // endianness mismatch. Byteswap all words read from the profiling // information. This can happen when the compiler host and target have // different endianness. bool ShouldByteSwap = (char)PacketType == 0; PacketType = ShouldByteSwap ? ByteSwap_32(PacketType) : PacketType; switch (PacketType) { case ArgumentInfo: ReadProfilingArgBlock(ToolName, F, ShouldByteSwap, CommandLines); break; case EdgeInfo: ReadProfilingBlock(ToolName, F, ShouldByteSwap, EdgeCounts); break; default: report_fatal_error(std::string(ToolName) + ": Unknown profiling packet type"); break; } } fclose(F); }