LLVM API Documentation

ProfileInfoLoader.cpp
Go to the documentation of this file.
00001 //===- ProfileInfoLoad.cpp - Load profile information from disk -----------===//
00002 //
00003 //                      The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 // The ProfileInfoLoader class is used to load and represent profiling
00011 // information read in from the dump file.
00012 //
00013 //===----------------------------------------------------------------------===//
00014 
00015 #include "llvm/Analysis/ProfileInfoLoader.h"
00016 #include "llvm/Analysis/ProfileInfoTypes.h"
00017 #include "llvm/IR/InstrTypes.h"
00018 #include "llvm/IR/Module.h"
00019 #include "llvm/Support/raw_ostream.h"
00020 #include <cstdio>
00021 #include <cstdlib>
00022 using namespace llvm;
00023 
00024 // ByteSwap - Byteswap 'Var' if 'Really' is true.
00025 //
00026 static inline unsigned ByteSwap(unsigned Var, bool Really) {
00027   if (!Really) return Var;
00028   return ((Var & (255U<< 0U)) << 24U) |
00029          ((Var & (255U<< 8U)) <<  8U) |
00030          ((Var & (255U<<16U)) >>  8U) |
00031          ((Var & (255U<<24U)) >> 24U);
00032 }
00033 
00034 static unsigned AddCounts(unsigned A, unsigned B) {
00035   // If either value is undefined, use the other.
00036   if (A == ProfileInfoLoader::Uncounted) return B;
00037   if (B == ProfileInfoLoader::Uncounted) return A;
00038   return A + B;
00039 }
00040 
00041 static void ReadProfilingBlock(const char *ToolName, FILE *F,
00042                                bool ShouldByteSwap,
00043                                std::vector<unsigned> &Data) {
00044   // Read the number of entries...
00045   unsigned NumEntries;
00046   if (fread(&NumEntries, sizeof(unsigned), 1, F) != 1) {
00047     errs() << ToolName << ": data packet truncated!\n";
00048     perror(0);
00049     exit(1);
00050   }
00051   NumEntries = ByteSwap(NumEntries, ShouldByteSwap);
00052 
00053   // Read the counts...
00054   std::vector<unsigned> TempSpace(NumEntries);
00055 
00056   // Read in the block of data...
00057   if (fread(&TempSpace[0], sizeof(unsigned)*NumEntries, 1, F) != 1) {
00058     errs() << ToolName << ": data packet truncated!\n";
00059     perror(0);
00060     exit(1);
00061   }
00062 
00063   // Make sure we have enough space... The space is initialised to -1 to
00064   // facitiltate the loading of missing values for OptimalEdgeProfiling.
00065   if (Data.size() < NumEntries)
00066     Data.resize(NumEntries, ProfileInfoLoader::Uncounted);
00067 
00068   // Accumulate the data we just read into the data.
00069   if (!ShouldByteSwap) {
00070     for (unsigned i = 0; i != NumEntries; ++i) {
00071       Data[i] = AddCounts(TempSpace[i], Data[i]);
00072     }
00073   } else {
00074     for (unsigned i = 0; i != NumEntries; ++i) {
00075       Data[i] = AddCounts(ByteSwap(TempSpace[i], true), Data[i]);
00076     }
00077   }
00078 }
00079 
00080 const unsigned ProfileInfoLoader::Uncounted = ~0U;
00081 
00082 // ProfileInfoLoader ctor - Read the specified profiling data file, exiting the
00083 // program if the file is invalid or broken.
00084 //
00085 ProfileInfoLoader::ProfileInfoLoader(const char *ToolName,
00086                                      const std::string &Filename)
00087   : Filename(Filename) {
00088   FILE *F = fopen(Filename.c_str(), "rb");
00089   if (F == 0) {
00090     errs() << ToolName << ": Error opening '" << Filename << "': ";
00091     perror(0);
00092     exit(1);
00093   }
00094 
00095   // Keep reading packets until we run out of them.
00096   unsigned PacketType;
00097   while (fread(&PacketType, sizeof(unsigned), 1, F) == 1) {
00098     // If the low eight bits of the packet are zero, we must be dealing with an
00099     // endianness mismatch.  Byteswap all words read from the profiling
00100     // information.
00101     bool ShouldByteSwap = (char)PacketType == 0;
00102     PacketType = ByteSwap(PacketType, ShouldByteSwap);
00103 
00104     switch (PacketType) {
00105     case ArgumentInfo: {
00106       unsigned ArgLength;
00107       if (fread(&ArgLength, sizeof(unsigned), 1, F) != 1) {
00108         errs() << ToolName << ": arguments packet truncated!\n";
00109         perror(0);
00110         exit(1);
00111       }
00112       ArgLength = ByteSwap(ArgLength, ShouldByteSwap);
00113 
00114       // Read in the arguments...
00115       std::vector<char> Chars(ArgLength+4);
00116 
00117       if (ArgLength)
00118         if (fread(&Chars[0], (ArgLength+3) & ~3, 1, F) != 1) {
00119           errs() << ToolName << ": arguments packet truncated!\n";
00120           perror(0);
00121           exit(1);
00122         }
00123       CommandLines.push_back(std::string(&Chars[0], &Chars[ArgLength]));
00124       break;
00125     }
00126 
00127     case FunctionInfo:
00128       ReadProfilingBlock(ToolName, F, ShouldByteSwap, FunctionCounts);
00129       break;
00130 
00131     case BlockInfo:
00132       ReadProfilingBlock(ToolName, F, ShouldByteSwap, BlockCounts);
00133       break;
00134 
00135     case EdgeInfo:
00136       ReadProfilingBlock(ToolName, F, ShouldByteSwap, EdgeCounts);
00137       break;
00138 
00139     case OptEdgeInfo:
00140       ReadProfilingBlock(ToolName, F, ShouldByteSwap, OptimalEdgeCounts);
00141       break;
00142 
00143     case BBTraceInfo:
00144       ReadProfilingBlock(ToolName, F, ShouldByteSwap, BBTrace);
00145       break;
00146 
00147     default:
00148       errs() << ToolName << ": Unknown packet type #" << PacketType << "!\n";
00149       exit(1);
00150     }
00151   }
00152 
00153   fclose(F);
00154 }
00155