mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-24 03:33:20 +01:00
3f515460eb
When dumping raw data from a stream, you might know the offset of a certain record you're interested in, as well as how long that record is. Previously, you had to dump the entire stream and wade through the bytes to find the interesting record. This patch allows you to specify an offset and length on the command line, and it will only dump the requested range. llvm-svn: 301607
384 lines
11 KiB
C++
384 lines
11 KiB
C++
//===-- ScopedPrinter.h ---------------------------------------------------===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef LLVM_SUPPORT_SCOPEDPRINTER_H
|
|
#define LLVM_SUPPORT_SCOPEDPRINTER_H
|
|
|
|
#include "llvm/ADT/APSInt.h"
|
|
#include "llvm/ADT/ArrayRef.h"
|
|
#include "llvm/ADT/SmallVector.h"
|
|
#include "llvm/ADT/StringRef.h"
|
|
#include "llvm/Support/DataTypes.h"
|
|
#include "llvm/Support/Endian.h"
|
|
#include "llvm/Support/raw_ostream.h"
|
|
#include <algorithm>
|
|
|
|
namespace llvm {
|
|
|
|
template <typename T> struct EnumEntry {
|
|
StringRef Name;
|
|
// While Name suffices in most of the cases, in certain cases
|
|
// GNU style and LLVM style of ELFDumper do not
|
|
// display same string for same enum. The AltName if initialized appropriately
|
|
// will hold the string that GNU style emits.
|
|
// Example:
|
|
// "EM_X86_64" string on LLVM style for Elf_Ehdr->e_machine corresponds to
|
|
// "Advanced Micro Devices X86-64" on GNU style
|
|
StringRef AltName;
|
|
T Value;
|
|
EnumEntry(StringRef N, StringRef A, T V) : Name(N), AltName(A), Value(V) {}
|
|
EnumEntry(StringRef N, T V) : Name(N), AltName(N), Value(V) {}
|
|
};
|
|
|
|
struct HexNumber {
|
|
// To avoid sign-extension we have to explicitly cast to the appropriate
|
|
// unsigned type. The overloads are here so that every type that is implicitly
|
|
// convertible to an integer (including enums and endian helpers) can be used
|
|
// without requiring type traits or call-site changes.
|
|
HexNumber(char Value) : Value(static_cast<unsigned char>(Value)) {}
|
|
HexNumber(signed char Value) : Value(static_cast<unsigned char>(Value)) {}
|
|
HexNumber(signed short Value) : Value(static_cast<unsigned short>(Value)) {}
|
|
HexNumber(signed int Value) : Value(static_cast<unsigned int>(Value)) {}
|
|
HexNumber(signed long Value) : Value(static_cast<unsigned long>(Value)) {}
|
|
HexNumber(signed long long Value)
|
|
: Value(static_cast<unsigned long long>(Value)) {}
|
|
HexNumber(unsigned char Value) : Value(Value) {}
|
|
HexNumber(unsigned short Value) : Value(Value) {}
|
|
HexNumber(unsigned int Value) : Value(Value) {}
|
|
HexNumber(unsigned long Value) : Value(Value) {}
|
|
HexNumber(unsigned long long Value) : Value(Value) {}
|
|
uint64_t Value;
|
|
};
|
|
|
|
raw_ostream &operator<<(raw_ostream &OS, const HexNumber &Value);
|
|
const std::string to_hexString(uint64_t Value, bool UpperCase = true);
|
|
|
|
template <class T> const std::string to_string(const T &Value) {
|
|
std::string number;
|
|
llvm::raw_string_ostream stream(number);
|
|
stream << Value;
|
|
return stream.str();
|
|
}
|
|
|
|
class ScopedPrinter {
|
|
public:
|
|
ScopedPrinter(raw_ostream &OS) : OS(OS), IndentLevel(0) {}
|
|
|
|
void flush() { OS.flush(); }
|
|
|
|
void indent(int Levels = 1) { IndentLevel += Levels; }
|
|
|
|
void unindent(int Levels = 1) {
|
|
IndentLevel = std::max(0, IndentLevel - Levels);
|
|
}
|
|
|
|
void resetIndent() { IndentLevel = 0; }
|
|
|
|
void setPrefix(StringRef P) { Prefix = P; }
|
|
|
|
void printIndent() {
|
|
OS << Prefix;
|
|
for (int i = 0; i < IndentLevel; ++i)
|
|
OS << " ";
|
|
}
|
|
|
|
template <typename T> HexNumber hex(T Value) { return HexNumber(Value); }
|
|
|
|
template <typename T, typename TEnum>
|
|
void printEnum(StringRef Label, T Value,
|
|
ArrayRef<EnumEntry<TEnum>> EnumValues) {
|
|
StringRef Name;
|
|
bool Found = false;
|
|
for (const auto &EnumItem : EnumValues) {
|
|
if (EnumItem.Value == Value) {
|
|
Name = EnumItem.Name;
|
|
Found = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (Found) {
|
|
startLine() << Label << ": " << Name << " (" << hex(Value) << ")\n";
|
|
} else {
|
|
startLine() << Label << ": " << hex(Value) << "\n";
|
|
}
|
|
}
|
|
|
|
template <typename T, typename TFlag>
|
|
void printFlags(StringRef Label, T Value, ArrayRef<EnumEntry<TFlag>> Flags,
|
|
TFlag EnumMask1 = {}, TFlag EnumMask2 = {},
|
|
TFlag EnumMask3 = {}) {
|
|
typedef EnumEntry<TFlag> FlagEntry;
|
|
typedef SmallVector<FlagEntry, 10> FlagVector;
|
|
FlagVector SetFlags;
|
|
|
|
for (const auto &Flag : Flags) {
|
|
if (Flag.Value == 0)
|
|
continue;
|
|
|
|
TFlag EnumMask{};
|
|
if (Flag.Value & EnumMask1)
|
|
EnumMask = EnumMask1;
|
|
else if (Flag.Value & EnumMask2)
|
|
EnumMask = EnumMask2;
|
|
else if (Flag.Value & EnumMask3)
|
|
EnumMask = EnumMask3;
|
|
bool IsEnum = (Flag.Value & EnumMask) != 0;
|
|
if ((!IsEnum && (Value & Flag.Value) == Flag.Value) ||
|
|
(IsEnum && (Value & EnumMask) == Flag.Value)) {
|
|
SetFlags.push_back(Flag);
|
|
}
|
|
}
|
|
|
|
std::sort(SetFlags.begin(), SetFlags.end(), &flagName<TFlag>);
|
|
|
|
startLine() << Label << " [ (" << hex(Value) << ")\n";
|
|
for (const auto &Flag : SetFlags) {
|
|
startLine() << " " << Flag.Name << " (" << hex(Flag.Value) << ")\n";
|
|
}
|
|
startLine() << "]\n";
|
|
}
|
|
|
|
template <typename T> void printFlags(StringRef Label, T Value) {
|
|
startLine() << Label << " [ (" << hex(Value) << ")\n";
|
|
uint64_t Flag = 1;
|
|
uint64_t Curr = Value;
|
|
while (Curr > 0) {
|
|
if (Curr & 1)
|
|
startLine() << " " << hex(Flag) << "\n";
|
|
Curr >>= 1;
|
|
Flag <<= 1;
|
|
}
|
|
startLine() << "]\n";
|
|
}
|
|
|
|
void printNumber(StringRef Label, uint64_t Value) {
|
|
startLine() << Label << ": " << Value << "\n";
|
|
}
|
|
|
|
void printNumber(StringRef Label, uint32_t Value) {
|
|
startLine() << Label << ": " << Value << "\n";
|
|
}
|
|
|
|
void printNumber(StringRef Label, uint16_t Value) {
|
|
startLine() << Label << ": " << Value << "\n";
|
|
}
|
|
|
|
void printNumber(StringRef Label, uint8_t Value) {
|
|
startLine() << Label << ": " << unsigned(Value) << "\n";
|
|
}
|
|
|
|
void printNumber(StringRef Label, int64_t Value) {
|
|
startLine() << Label << ": " << Value << "\n";
|
|
}
|
|
|
|
void printNumber(StringRef Label, int32_t Value) {
|
|
startLine() << Label << ": " << Value << "\n";
|
|
}
|
|
|
|
void printNumber(StringRef Label, int16_t Value) {
|
|
startLine() << Label << ": " << Value << "\n";
|
|
}
|
|
|
|
void printNumber(StringRef Label, int8_t Value) {
|
|
startLine() << Label << ": " << int(Value) << "\n";
|
|
}
|
|
|
|
void printNumber(StringRef Label, const APSInt &Value) {
|
|
startLine() << Label << ": " << Value << "\n";
|
|
}
|
|
|
|
void printBoolean(StringRef Label, bool Value) {
|
|
startLine() << Label << ": " << (Value ? "Yes" : "No") << '\n';
|
|
}
|
|
|
|
template <typename... T> void printVersion(StringRef Label, T... Version) {
|
|
startLine() << Label << ": ";
|
|
printVersionInternal(Version...);
|
|
getOStream() << "\n";
|
|
}
|
|
|
|
template <typename T> void printList(StringRef Label, const T &List) {
|
|
startLine() << Label << ": [";
|
|
bool Comma = false;
|
|
for (const auto &Item : List) {
|
|
if (Comma)
|
|
OS << ", ";
|
|
OS << Item;
|
|
Comma = true;
|
|
}
|
|
OS << "]\n";
|
|
}
|
|
|
|
template <typename T, typename U>
|
|
void printList(StringRef Label, const T &List, const U &Printer) {
|
|
startLine() << Label << ": [";
|
|
bool Comma = false;
|
|
for (const auto &Item : List) {
|
|
if (Comma)
|
|
OS << ", ";
|
|
Printer(OS, Item);
|
|
Comma = true;
|
|
}
|
|
OS << "]\n";
|
|
}
|
|
|
|
template <typename T> void printHexList(StringRef Label, const T &List) {
|
|
startLine() << Label << ": [";
|
|
bool Comma = false;
|
|
for (const auto &Item : List) {
|
|
if (Comma)
|
|
OS << ", ";
|
|
OS << hex(Item);
|
|
Comma = true;
|
|
}
|
|
OS << "]\n";
|
|
}
|
|
|
|
template <typename T> void printHex(StringRef Label, T Value) {
|
|
startLine() << Label << ": " << hex(Value) << "\n";
|
|
}
|
|
|
|
template <typename T> void printHex(StringRef Label, StringRef Str, T Value) {
|
|
startLine() << Label << ": " << Str << " (" << hex(Value) << ")\n";
|
|
}
|
|
|
|
template <typename T>
|
|
void printSymbolOffset(StringRef Label, StringRef Symbol, T Value) {
|
|
startLine() << Label << ": " << Symbol << '+' << hex(Value) << '\n';
|
|
}
|
|
|
|
void printString(StringRef Value) { startLine() << Value << "\n"; }
|
|
|
|
void printString(StringRef Label, StringRef Value) {
|
|
startLine() << Label << ": " << Value << "\n";
|
|
}
|
|
|
|
void printString(StringRef Label, const std::string &Value) {
|
|
startLine() << Label << ": " << Value << "\n";
|
|
}
|
|
|
|
template <typename T>
|
|
void printNumber(StringRef Label, StringRef Str, T Value) {
|
|
startLine() << Label << ": " << Str << " (" << Value << ")\n";
|
|
}
|
|
|
|
void printBinary(StringRef Label, StringRef Str, ArrayRef<uint8_t> Value) {
|
|
printBinaryImpl(Label, Str, Value, false);
|
|
}
|
|
|
|
void printBinary(StringRef Label, StringRef Str, ArrayRef<char> Value) {
|
|
auto V = makeArrayRef(reinterpret_cast<const uint8_t *>(Value.data()),
|
|
Value.size());
|
|
printBinaryImpl(Label, Str, V, false);
|
|
}
|
|
|
|
void printBinary(StringRef Label, ArrayRef<uint8_t> Value) {
|
|
printBinaryImpl(Label, StringRef(), Value, false);
|
|
}
|
|
|
|
void printBinary(StringRef Label, ArrayRef<char> Value) {
|
|
auto V = makeArrayRef(reinterpret_cast<const uint8_t *>(Value.data()),
|
|
Value.size());
|
|
printBinaryImpl(Label, StringRef(), V, false);
|
|
}
|
|
|
|
void printBinary(StringRef Label, StringRef Value) {
|
|
auto V = makeArrayRef(reinterpret_cast<const uint8_t *>(Value.data()),
|
|
Value.size());
|
|
printBinaryImpl(Label, StringRef(), V, false);
|
|
}
|
|
|
|
void printBinaryBlock(StringRef Label, ArrayRef<uint8_t> Value,
|
|
uint32_t StartOffset) {
|
|
printBinaryImpl(Label, StringRef(), Value, true, StartOffset);
|
|
}
|
|
|
|
void printBinaryBlock(StringRef Label, ArrayRef<uint8_t> Value) {
|
|
printBinaryImpl(Label, StringRef(), Value, true);
|
|
}
|
|
|
|
void printBinaryBlock(StringRef Label, StringRef Value) {
|
|
auto V = makeArrayRef(reinterpret_cast<const uint8_t *>(Value.data()),
|
|
Value.size());
|
|
printBinaryImpl(Label, StringRef(), V, true);
|
|
}
|
|
|
|
template <typename T> void printObject(StringRef Label, const T &Value) {
|
|
startLine() << Label << ": " << Value << "\n";
|
|
}
|
|
|
|
raw_ostream &startLine() {
|
|
printIndent();
|
|
return OS;
|
|
}
|
|
|
|
raw_ostream &getOStream() { return OS; }
|
|
|
|
private:
|
|
template <typename T> void printVersionInternal(T Value) {
|
|
getOStream() << Value;
|
|
}
|
|
|
|
template <typename S, typename T, typename... TArgs>
|
|
void printVersionInternal(S Value, T Value2, TArgs... Args) {
|
|
getOStream() << Value << ".";
|
|
printVersionInternal(Value2, Args...);
|
|
}
|
|
|
|
template <typename T>
|
|
static bool flagName(const EnumEntry<T> &lhs, const EnumEntry<T> &rhs) {
|
|
return lhs.Name < rhs.Name;
|
|
}
|
|
|
|
void printBinaryImpl(StringRef Label, StringRef Str, ArrayRef<uint8_t> Value,
|
|
bool Block, uint32_t StartOffset = 0);
|
|
|
|
raw_ostream &OS;
|
|
int IndentLevel;
|
|
StringRef Prefix;
|
|
};
|
|
|
|
template <>
|
|
inline void
|
|
ScopedPrinter::printHex<support::ulittle16_t>(StringRef Label,
|
|
support::ulittle16_t Value) {
|
|
startLine() << Label << ": " << hex(Value) << "\n";
|
|
}
|
|
|
|
template<char Open, char Close>
|
|
struct DelimitedScope {
|
|
explicit DelimitedScope(ScopedPrinter &W) : W(W) {
|
|
W.startLine() << Open << '\n';
|
|
W.indent();
|
|
}
|
|
|
|
DelimitedScope(ScopedPrinter &W, StringRef N) : W(W) {
|
|
W.startLine() << N;
|
|
if (!N.empty())
|
|
W.getOStream() << ' ';
|
|
W.getOStream() << Open << '\n';
|
|
W.indent();
|
|
}
|
|
|
|
~DelimitedScope() {
|
|
W.unindent();
|
|
W.startLine() << Close << '\n';
|
|
}
|
|
|
|
ScopedPrinter &W;
|
|
};
|
|
|
|
using DictScope = DelimitedScope<'{', '}'>;
|
|
using ListScope = DelimitedScope<'[', ']'>;
|
|
|
|
} // namespace llvm
|
|
|
|
#endif
|