1 //===- ProfileDataLoader.cpp - Load profile information from disk ---------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // The ProfileDataLoader class is used to load raw profiling data from the dump 11 // file. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #include "llvm/Analysis/ProfileDataLoader.h" 16 #include "llvm/ADT/ArrayRef.h" 17 #include "llvm/ADT/OwningPtr.h" 18 #include "llvm/Analysis/ProfileDataTypes.h" 19 #include "llvm/IR/InstrTypes.h" 20 #include "llvm/IR/Module.h" 21 #include "llvm/Support/raw_ostream.h" 22 #include "llvm/Support/system_error.h" 23 #include <cstdio> 24 #include <cstdlib> 25 using namespace llvm; 26 27 raw_ostream &llvm::operator<<(raw_ostream &O, std::pair<const BasicBlock *, 28 const BasicBlock *> E) { 29 O << "("; 30 31 if (E.first) 32 O << E.first->getName(); 33 else 34 O << "0"; 35 36 O << ","; 37 38 if (E.second) 39 O << E.second->getName(); 40 else 41 O << "0"; 42 43 return O << ")"; 44 } 45 46 /// AddCounts - Add 'A' and 'B', accounting for the fact that the value of one 47 /// (or both) may not be defined. 48 static unsigned AddCounts(unsigned A, unsigned B) { 49 // If either value is undefined, use the other. 50 // Undefined + undefined = undefined. 51 if (A == ProfileDataLoader::Uncounted) return B; 52 if (B == ProfileDataLoader::Uncounted) return A; 53 54 return A + B; 55 } 56 57 /// ReadProfilingData - Load 'NumEntries' items of type 'T' from file 'F' 58 template <typename T> 59 static void ReadProfilingData(const char *ToolName, FILE *F, 60 T *Data, size_t NumEntries) { 61 // Read in the block of data... 62 if (fread(Data, sizeof(T), NumEntries, F) != NumEntries) 63 report_fatal_error(Twine(ToolName) + ": Profiling data truncated"); 64 } 65 66 /// ReadProfilingNumEntries - Read how many entries are in this profiling data 67 /// packet. 68 static unsigned ReadProfilingNumEntries(const char *ToolName, FILE *F, 69 bool ShouldByteSwap) { 70 unsigned Entry; 71 ReadProfilingData<unsigned>(ToolName, F, &Entry, 1); 72 return ShouldByteSwap ? ByteSwap_32(Entry) : Entry; 73 } 74 75 /// ReadProfilingBlock - Read the number of entries in the next profiling data 76 /// packet and then accumulate the entries into 'Data'. 77 static void ReadProfilingBlock(const char *ToolName, FILE *F, 78 bool ShouldByteSwap, 79 SmallVectorImpl<unsigned> &Data) { 80 // Read the number of entries... 81 unsigned NumEntries = ReadProfilingNumEntries(ToolName, F, ShouldByteSwap); 82 83 // Read in the data. 84 SmallVector<unsigned, 8> TempSpace(NumEntries); 85 ReadProfilingData<unsigned>(ToolName, F, TempSpace.data(), NumEntries); 86 87 // Make sure we have enough space ... 88 if (Data.size() < NumEntries) 89 Data.resize(NumEntries, ProfileDataLoader::Uncounted); 90 91 // Accumulate the data we just read into the existing data. 92 for (unsigned i = 0; i < NumEntries; ++i) { 93 unsigned Entry = ShouldByteSwap ? ByteSwap_32(TempSpace[i]) : TempSpace[i]; 94 Data[i] = AddCounts(Entry, Data[i]); 95 } 96 } 97 98 /// ReadProfilingArgBlock - Read the command line arguments that the progam was 99 /// run with when the current profiling data packet(s) were generated. 100 static void ReadProfilingArgBlock(const char *ToolName, FILE *F, 101 bool ShouldByteSwap, 102 SmallVectorImpl<std::string> &CommandLines) { 103 // Read the number of bytes ... 104 unsigned ArgLength = ReadProfilingNumEntries(ToolName, F, ShouldByteSwap); 105 106 // Read in the arguments (if there are any to read). Round up the length to 107 // the nearest 4-byte multiple. 108 SmallVector<char, 8> Args(ArgLength+4); 109 if (ArgLength) 110 ReadProfilingData<char>(ToolName, F, Args.data(), (ArgLength+3) & ~3); 111 112 // Store the arguments. 113 CommandLines.push_back(std::string(&Args[0], &Args[ArgLength])); 114 } 115 116 const unsigned ProfileDataLoader::Uncounted = ~0U; 117 118 /// ProfileDataLoader ctor - Read the specified profiling data file, reporting 119 /// a fatal error if the file is invalid or broken. 120 ProfileDataLoader::ProfileDataLoader(const char *ToolName, 121 const std::string &Filename) 122 : Filename(Filename) { 123 FILE *F = fopen(Filename.c_str(), "rb"); 124 if (F == 0) 125 report_fatal_error(Twine(ToolName) + ": Error opening '" + 126 Filename + "': "); 127 128 // Keep reading packets until we run out of them. 129 unsigned PacketType; 130 while (fread(&PacketType, sizeof(unsigned), 1, F) == 1) { 131 // If the low eight bits of the packet are zero, we must be dealing with an 132 // endianness mismatch. Byteswap all words read from the profiling 133 // information. This can happen when the compiler host and target have 134 // different endianness. 135 bool ShouldByteSwap = (char)PacketType == 0; 136 PacketType = ShouldByteSwap ? ByteSwap_32(PacketType) : PacketType; 137 138 switch (PacketType) { 139 case ArgumentInfo: 140 ReadProfilingArgBlock(ToolName, F, ShouldByteSwap, CommandLines); 141 break; 142 143 case EdgeInfo: 144 ReadProfilingBlock(ToolName, F, ShouldByteSwap, EdgeCounts); 145 break; 146 147 default: 148 report_fatal_error(std::string(ToolName) 149 + ": Unknown profiling packet type"); 150 break; 151 } 152 } 153 154 fclose(F); 155 } 156