llvm/bolt/DataReader.h
Rafael Auler 4c1da22ae9 Add branch count information to binary CFG
Summary:
Changes DataReader to organize branch perf data per function name and
sets up logistics to bring this data to BinaryFunction::buildCFG(). To do this,
we expand BinaryContext with a const reference to DataReader. This patch also
adds the "-dump-functions" flag to force llvm-flo to dump the current state of
BinaryFunctions once they are disassembled and their CFG built, allowing us to
test whether the builder is sane with LLVM LIT tests.

(cherry picked from FBD2534675)
2015-10-12 12:30:47 -07:00

128 lines
3.7 KiB
C++

//===-- Reader/DataReader.h - Perf data reader ------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This family of functions reads profile data written by the perf2flo
// utility and stores it in memory for llvm-flo consumption.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_TOOLS_LLVM_FLO_DATA_READER_H
#define LLVM_TOOLS_LLVM_FLO_DATA_READER_H
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/Errc.h"
#include "llvm/Support/ErrorOr.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/raw_ostream.h"
namespace llvm {
namespace flo {
struct Location {
bool IsSymbol;
StringRef Name;
uint64_t Offset;
Location(bool IsSymbol, StringRef Name, uint64_t Offset)
: IsSymbol(IsSymbol), Name(Name), Offset(Offset) {}
};
struct BranchInfo {
Location From;
Location To;
int64_t Mispreds;
int64_t Branches;
BranchInfo(Location From, Location To, int64_t Mispreds, int64_t Branches)
: From(std::move(From)), To(std::move(To)), Mispreds(Mispreds),
Branches(Branches) {}
};
class FuncBranchData {
public:
typedef std::vector<BranchInfo> ContainerTy;
StringRef Name;
ContainerTy Data;
FuncBranchData(StringRef Name, ContainerTy Data)
: Name(Name), Data(std::move(Data)) {}
ErrorOr<const BranchInfo &> getBranch(uint64_t From, uint64_t To) const;
uint64_t countBranchesTo(StringRef FuncName) const;
};
//===----------------------------------------------------------------------===//
//
/// DataReader Class
///
class DataReader {
public:
explicit DataReader(raw_ostream &Diag) : Diag(Diag) {}
DataReader(std::unique_ptr<MemoryBuffer> MemBuf, raw_ostream &Diag)
: FileBuf(std::move(MemBuf)), Diag(Diag), ParsingBuf(FileBuf->getBuffer()),
Line(0), Col(0) {}
static ErrorOr<std::unique_ptr<DataReader>> readPerfData(StringRef Path,
raw_ostream &Diag);
/// Parses the input flo data file into internal data structures. We expect
/// the file format to follow the syntax below.
///
/// <is symbol?> <closest elf symbol or DSO name> <relative FROM address>
/// <is symbol?> <closest elf symbol or DSO name> <relative TO address>
/// <number of mispredictions> <number of branches>
///
/// In <is symbol?> field we record 0 if our closest address is a DSO load
/// address or 1 if our closest address is an ELF symbol.
///
/// Example:
///
/// 1 main 3fb 0 /lib/ld-2.21.so 12 4 221
///
/// The example records branches from symbol main, offset 3fb, to DSO ld-2.21,
/// offset 12, with 4 mispredictions and 221 branches
std::error_code parse();
ErrorOr<const FuncBranchData &> getFuncBranchData(StringRef FuncName) const;
uint64_t countBranchesTo(StringRef FuncName) const;
/// Dumps the entire data structures parsed. Used for debugging.
void dump() const;
private:
void reportError(StringRef ErrorMsg);
bool expectAndConsumeFS();
ErrorOr<StringRef> parseString(char EndChar);
ErrorOr<int64_t> parseNumberField(char EndChar);
ErrorOr<Location> parseLocation();
ErrorOr<BranchInfo> parseBranchInfo();
bool hasData();
// An in-memory copy of the input data file - owns strings used in reader
std::unique_ptr<MemoryBuffer> FileBuf;
raw_ostream &Diag;
StringRef ParsingBuf;
unsigned Line;
unsigned Col;
StringMap<FuncBranchData> FuncsMap;
static const char FieldSeparator = ' ';
};
}
}
#endif