blob: acafdfb3eb830ac36bdfcb0affe83d75feaae00b [file] [log] [blame]
Chris Lattnere4367792003-10-28 20:13:07 +00001//===- ProfileInfo.cpp - Represents profile information -------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file was developed by the LLVM research group and is distributed under
6// the University of Illinois Open Source License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// The ProfileInfo class is used to represent profiling information read in from
11// the dump file.
12//
13//===----------------------------------------------------------------------===//
14
15#include "ProfileInfo.h"
16#include <iostream>
17#include <sys/types.h>
18#include <sys/stat.h>
19#include <fcntl.h>
20#include <stdio.h>
21
22enum ProfilingType {
23 Arguments = 1, // The command line argument block
24 Function = 2, // Function profiling information
25 Block = 3, // Block profiling information
26};
27
28// ByteSwap - Byteswap 'Var' if 'Really' is true.
29//
30static inline unsigned ByteSwap(unsigned Var, bool Really) {
31 if (!Really) return Var;
32 return ((Var & (255<< 0)) << 24) |
33 ((Var & (255<< 8)) << 8) |
34 ((Var & (255<<16)) >> 8) |
35 ((Var & (255<<24)) >> 24);
36}
37
38static void ReadProfilingBlock(const char *ToolName, FILE *F,
39 bool ShouldByteSwap,
40 std::vector<unsigned> &Data) {
41 // Read the number of entries...
42 unsigned NumEntries;
43 if (fread(&NumEntries, sizeof(unsigned), 1, F) != 1) {
44 std::cerr << ToolName << ": data packet truncated!\n";
45 perror(0);
46 exit(1);
47 }
48 NumEntries = ByteSwap(NumEntries, ShouldByteSwap);
49
50 // Read the counts...
51 std::vector<unsigned> TempSpace(NumEntries);
52
53 // Read in the block of data...
54 if (fread(&TempSpace[0], sizeof(unsigned)*NumEntries, 1, F) != 1) {
55 std::cerr << ToolName << ": data packet truncated!\n";
56 perror(0);
57 exit(1);
58 }
59
60 // Make sure we have enough space...
61 if (Data.size() < NumEntries)
62 Data.resize(NumEntries);
63
64 // Accumulate the data we just read into the data.
65 if (!ShouldByteSwap) {
66 for (unsigned i = 0; i != NumEntries; ++i)
67 Data[i] += TempSpace[i];
68 } else {
69 for (unsigned i = 0; i != NumEntries; ++i)
70 Data[i] += ByteSwap(TempSpace[i], true);
71 }
72}
73
74// ProfileInfo ctor - Read the specified profiling data file, exiting the
75// program if the file is invalid or broken.
76//
77ProfileInfo::ProfileInfo(const char *ToolName, const std::string &Filename) {
78 FILE *F = fopen(Filename.c_str(), "r");
79 if (F == 0) {
80 std::cerr << ToolName << ": Error opening '" << Filename << ": ";
81 perror(0);
82 exit(1);
83 }
84
85 // Keep reading packets until we run out of them.
86 unsigned PacketType;
87 while (fread(&PacketType, sizeof(unsigned), 1, F) == 1) {
88 // If the low eight bits of the packet are zero, we must be dealing with an
89 // endianness mismatch. Byteswap all words read from the profiling
90 // information.
91 bool ShouldByteSwap = (char)PacketType == 0;
92 PacketType = ByteSwap(PacketType, ShouldByteSwap);
93
94 switch (PacketType) {
95 case Arguments: {
96 unsigned ArgLength;
97 if (fread(&ArgLength, sizeof(unsigned), 1, F) != 1) {
98 std::cerr << ToolName << ": arguments packet truncated!\n";
99 perror(0);
100 exit(1);
101 }
102 ArgLength = ByteSwap(ArgLength, ShouldByteSwap);
103
104 // Read in the arguments...
105 std::vector<char> Chars(ArgLength+4);
106
107 if (ArgLength)
108 if (fread(&Chars[0], (ArgLength+3) & ~3, 1, F) != 1) {
109 std::cerr << ToolName << ": arguments packet truncated!\n";
110 perror(0);
111 exit(1);
112 }
113 CommandLines.push_back(std::string(&Chars[0], &Chars[ArgLength]));
114 break;
115 }
116
117 case Function:
118 ReadProfilingBlock(ToolName, F, ShouldByteSwap, FunctionCounts);
119 break;
120
121 case Block:
122 ReadProfilingBlock(ToolName, F, ShouldByteSwap, BlockCounts);
123 break;
124
125 default:
126 std::cerr << ToolName << ": Unknown packet type #" << PacketType << "!\n";
127 exit(1);
128 }
129 }
130
131 fclose(F);
132}