1de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar//===-- ScopedPrinter.h ---------------------------------------------------===//
276e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher//
376e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher//                     The LLVM Compiler Infrastructure
476e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher//
576e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher// This file is distributed under the University of Illinois Open Source
676e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher// License. See LICENSE.TXT for details.
776e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher//
876e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher//===----------------------------------------------------------------------===//
976e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher
10de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar#ifndef LLVM_SUPPORT_SCOPEDPRINTER_H
11de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar#define LLVM_SUPPORT_SCOPEDPRINTER_H
1276e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher
13de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar#include "llvm/ADT/APSInt.h"
1476e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher#include "llvm/ADT/ArrayRef.h"
1576e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher#include "llvm/ADT/SmallVector.h"
1636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines#include "llvm/ADT/StringRef.h"
1776e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher#include "llvm/Support/DataTypes.h"
1876e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher#include "llvm/Support/Endian.h"
1976e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher#include "llvm/Support/raw_ostream.h"
2076e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher#include <algorithm>
2176e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher
2276e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christophernamespace llvm {
2376e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher
24de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainartemplate <typename T> struct EnumEntry {
2576e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher  StringRef Name;
26de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  // While Name suffices in most of the cases, in certain cases
27de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  // GNU style and LLVM style of ELFDumper do not
28de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  // display same string for same enum. The AltName if initialized appropriately
29de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  // will hold the string that GNU style emits.
30de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  // Example:
31de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  // "EM_X86_64" string on LLVM style for Elf_Ehdr->e_machine corresponds to
32de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  // "Advanced Micro Devices X86-64" on GNU style
33de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  StringRef AltName;
3476e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher  T Value;
35de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  EnumEntry(StringRef N, StringRef A, T V) : Name(N), AltName(A), Value(V) {}
36de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  EnumEntry(StringRef N, T V) : Name(N), AltName(N), Value(V) {}
3776e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher};
3876e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher
3976e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopherstruct HexNumber {
4076e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher  // To avoid sign-extension we have to explicitly cast to the appropriate
4176e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher  // unsigned type. The overloads are here so that every type that is implicitly
4276e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher  // convertible to an integer (including enums and endian helpers) can be used
4376e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher  // without requiring type traits or call-site changes.
44de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  HexNumber(char Value) : Value(static_cast<unsigned char>(Value)) {}
45de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  HexNumber(signed char Value) : Value(static_cast<unsigned char>(Value)) {}
46de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  HexNumber(signed short Value) : Value(static_cast<unsigned short>(Value)) {}
47de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  HexNumber(signed int Value) : Value(static_cast<unsigned int>(Value)) {}
48de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  HexNumber(signed long Value) : Value(static_cast<unsigned long>(Value)) {}
49de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  HexNumber(signed long long Value)
50de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar      : Value(static_cast<unsigned long long>(Value)) {}
51de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  HexNumber(unsigned char Value) : Value(Value) {}
52de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  HexNumber(unsigned short Value) : Value(Value) {}
53de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  HexNumber(unsigned int Value) : Value(Value) {}
54de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  HexNumber(unsigned long Value) : Value(Value) {}
55de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  HexNumber(unsigned long long Value) : Value(Value) {}
5676e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher  uint64_t Value;
5776e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher};
5876e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher
59de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarraw_ostream &operator<<(raw_ostream &OS, const HexNumber &Value);
60de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarconst std::string to_hexString(uint64_t Value, bool UpperCase = true);
61de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
62de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainartemplate <class T> const std::string to_string(const T &Value) {
63de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  std::string number;
64de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  llvm::raw_string_ostream stream(number);
65de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  stream << Value;
66de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  return stream.str();
67de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar}
6876e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher
69de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarclass ScopedPrinter {
7076e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopherpublic:
71de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  ScopedPrinter(raw_ostream &OS) : OS(OS), IndentLevel(0) {}
7276e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher
73de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  void flush() { OS.flush(); }
7476e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher
75de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  void indent(int Levels = 1) { IndentLevel += Levels; }
7676e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher
7776e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher  void unindent(int Levels = 1) {
7876e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher    IndentLevel = std::max(0, IndentLevel - Levels);
7976e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher  }
8076e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher
81de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  void resetIndent() { IndentLevel = 0; }
82de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
83de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  void setPrefix(StringRef P) { Prefix = P; }
84de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
8576e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher  void printIndent() {
86de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    OS << Prefix;
8776e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher    for (int i = 0; i < IndentLevel; ++i)
8876e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher      OS << "  ";
8976e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher  }
9076e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher
91de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  template <typename T> HexNumber hex(T Value) { return HexNumber(Value); }
9276e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher
93de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  template <typename T, typename TEnum>
9476e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher  void printEnum(StringRef Label, T Value,
95de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar                 ArrayRef<EnumEntry<TEnum>> EnumValues) {
9676e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher    StringRef Name;
9776e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher    bool Found = false;
98dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    for (const auto &EnumItem : EnumValues) {
99dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines      if (EnumItem.Value == Value) {
100dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        Name = EnumItem.Name;
10176e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher        Found = true;
10276e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher        break;
10376e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher      }
10476e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher    }
10576e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher
10676e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher    if (Found) {
10776e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher      startLine() << Label << ": " << Name << " (" << hex(Value) << ")\n";
10876e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher    } else {
10976e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher      startLine() << Label << ": " << hex(Value) << "\n";
11076e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher    }
11176e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher  }
11276e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher
1136948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar  template <typename T, typename TFlag>
1146948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar  void printFlags(StringRef Label, T Value, ArrayRef<EnumEntry<TFlag>> Flags,
1156948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar                  TFlag EnumMask1 = {}, TFlag EnumMask2 = {},
1166948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar                  TFlag EnumMask3 = {}) {
11776e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher    typedef EnumEntry<TFlag> FlagEntry;
11876e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher    typedef SmallVector<FlagEntry, 10> FlagVector;
11976e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher    FlagVector SetFlags;
12076e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher
121dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    for (const auto &Flag : Flags) {
122dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines      if (Flag.Value == 0)
12376e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher        continue;
12476e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher
1256948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar      TFlag EnumMask{};
1266948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar      if (Flag.Value & EnumMask1)
1276948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar        EnumMask = EnumMask1;
1286948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar      else if (Flag.Value & EnumMask2)
1296948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar        EnumMask = EnumMask2;
1306948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar      else if (Flag.Value & EnumMask3)
1316948897e478cbd66626159776a8017b3c18579b9Pirama Arumuga Nainar        EnumMask = EnumMask3;
132dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines      bool IsEnum = (Flag.Value & EnumMask) != 0;
133dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines      if ((!IsEnum && (Value & Flag.Value) == Flag.Value) ||
134de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar          (IsEnum && (Value & EnumMask) == Flag.Value)) {
135dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        SetFlags.push_back(Flag);
13676e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher      }
13776e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher    }
13876e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher
13976e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher    std::sort(SetFlags.begin(), SetFlags.end(), &flagName<TFlag>);
14076e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher
14176e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher    startLine() << Label << " [ (" << hex(Value) << ")\n";
142dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    for (const auto &Flag : SetFlags) {
143dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines      startLine() << "  " << Flag.Name << " (" << hex(Flag.Value) << ")\n";
14476e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher    }
14576e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher    startLine() << "]\n";
14676e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher  }
14776e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher
148de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  template <typename T> void printFlags(StringRef Label, T Value) {
14976e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher    startLine() << Label << " [ (" << hex(Value) << ")\n";
15076e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher    uint64_t Flag = 1;
15176e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher    uint64_t Curr = Value;
15276e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher    while (Curr > 0) {
15376e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher      if (Curr & 1)
15476e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher        startLine() << "  " << hex(Flag) << "\n";
15576e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher      Curr >>= 1;
15676e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher      Flag <<= 1;
15776e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher    }
15876e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher    startLine() << "]\n";
15976e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher  }
16076e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher
16176e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher  void printNumber(StringRef Label, uint64_t Value) {
16276e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher    startLine() << Label << ": " << Value << "\n";
16376e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher  }
16476e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher
16576e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher  void printNumber(StringRef Label, uint32_t Value) {
16676e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher    startLine() << Label << ": " << Value << "\n";
16776e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher  }
16876e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher
16976e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher  void printNumber(StringRef Label, uint16_t Value) {
17076e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher    startLine() << Label << ": " << Value << "\n";
17176e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher  }
17276e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher
17376e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher  void printNumber(StringRef Label, uint8_t Value) {
17476e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher    startLine() << Label << ": " << unsigned(Value) << "\n";
17576e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher  }
17676e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher
17776e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher  void printNumber(StringRef Label, int64_t Value) {
17876e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher    startLine() << Label << ": " << Value << "\n";
17976e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher  }
18076e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher
18176e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher  void printNumber(StringRef Label, int32_t Value) {
18276e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher    startLine() << Label << ": " << Value << "\n";
18376e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher  }
18476e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher
18576e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher  void printNumber(StringRef Label, int16_t Value) {
18676e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher    startLine() << Label << ": " << Value << "\n";
18776e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher  }
18876e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher
18976e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher  void printNumber(StringRef Label, int8_t Value) {
19076e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher    startLine() << Label << ": " << int(Value) << "\n";
19176e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher  }
19276e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher
193de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  void printNumber(StringRef Label, const APSInt &Value) {
194de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    startLine() << Label << ": " << Value << "\n";
195de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  }
196de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
197c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines  void printBoolean(StringRef Label, bool Value) {
198c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines    startLine() << Label << ": " << (Value ? "Yes" : "No") << '\n';
199c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines  }
200c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines
201de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  template <typename... T> void printVersion(StringRef Label, T... Version) {
202de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    startLine() << Label << ": ";
203de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    printVersionInternal(Version...);
204de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    getOStream() << "\n";
205de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  }
206de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
207de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  template <typename T> void printList(StringRef Label, const T &List) {
20836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    startLine() << Label << ": [";
20936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    bool Comma = false;
210dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    for (const auto &Item : List) {
21136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      if (Comma)
21236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines        OS << ", ";
213dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines      OS << Item;
21436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines      Comma = true;
21536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    }
21636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    OS << "]\n";
21736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  }
21836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
219de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  template <typename T, typename U>
220de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  void printList(StringRef Label, const T &List, const U &Printer) {
221de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    startLine() << Label << ": [";
222de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    bool Comma = false;
223de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    for (const auto &Item : List) {
224de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar      if (Comma)
225de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar        OS << ", ";
226de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar      Printer(OS, Item);
227de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar      Comma = true;
228de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    }
229de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    OS << "]\n";
230de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  }
231de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
232de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  template <typename T> void printHexList(StringRef Label, const T &List) {
233f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar    startLine() << Label << ": [";
234f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar    bool Comma = false;
235f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar    for (const auto &Item : List) {
236f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar      if (Comma)
237f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar        OS << ", ";
238f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar      OS << hex(Item);
239f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar      Comma = true;
240f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar    }
241f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar    OS << "]\n";
242f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar  }
243f3ef5332fa3f4d5ec72c178a2b19dac363a19383Pirama Arumuga Nainar
244de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  template <typename T> void printHex(StringRef Label, T Value) {
24576e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher    startLine() << Label << ": " << hex(Value) << "\n";
24676e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher  }
24776e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher
248de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  template <typename T> void printHex(StringRef Label, StringRef Str, T Value) {
24976e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher    startLine() << Label << ": " << Str << " (" << hex(Value) << ")\n";
25076e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher  }
25176e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher
252de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  template <typename T>
253de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  void printSymbolOffset(StringRef Label, StringRef Symbol, T Value) {
254de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    startLine() << Label << ": " << Symbol << '+' << hex(Value) << '\n';
255de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  }
256de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
257de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  void printString(StringRef Value) { startLine() << Value << "\n"; }
258de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
25976e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher  void printString(StringRef Label, StringRef Value) {
26076e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher    startLine() << Label << ": " << Value << "\n";
26176e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher  }
26276e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher
26376e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher  void printString(StringRef Label, const std::string &Value) {
26476e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher    startLine() << Label << ": " << Value << "\n";
26576e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher  }
26676e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher
267de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  template <typename T>
26876e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher  void printNumber(StringRef Label, StringRef Str, T Value) {
26976e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher    startLine() << Label << ": " << Str << " (" << Value << ")\n";
27076e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher  }
27176e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher
27276e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher  void printBinary(StringRef Label, StringRef Str, ArrayRef<uint8_t> Value) {
27376e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher    printBinaryImpl(Label, Str, Value, false);
27476e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher  }
27576e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher
27676e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher  void printBinary(StringRef Label, StringRef Str, ArrayRef<char> Value) {
277de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    auto V = makeArrayRef(reinterpret_cast<const uint8_t *>(Value.data()),
27837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines                          Value.size());
27976e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher    printBinaryImpl(Label, Str, V, false);
28076e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher  }
28176e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher
28276e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher  void printBinary(StringRef Label, ArrayRef<uint8_t> Value) {
28376e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher    printBinaryImpl(Label, StringRef(), Value, false);
28476e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher  }
28576e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher
28676e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher  void printBinary(StringRef Label, ArrayRef<char> Value) {
287de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    auto V = makeArrayRef(reinterpret_cast<const uint8_t *>(Value.data()),
28837ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines                          Value.size());
28976e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher    printBinaryImpl(Label, StringRef(), V, false);
29076e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher  }
29176e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher
29276e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher  void printBinary(StringRef Label, StringRef Value) {
293de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    auto V = makeArrayRef(reinterpret_cast<const uint8_t *>(Value.data()),
29437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines                          Value.size());
29576e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher    printBinaryImpl(Label, StringRef(), V, false);
29676e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher  }
29776e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher
298de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  void printBinaryBlock(StringRef Label, ArrayRef<uint8_t> Value) {
299de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    printBinaryImpl(Label, StringRef(), Value, true);
300de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  }
301de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
30276e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher  void printBinaryBlock(StringRef Label, StringRef Value) {
303de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    auto V = makeArrayRef(reinterpret_cast<const uint8_t *>(Value.data()),
30437ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines                          Value.size());
30576e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher    printBinaryImpl(Label, StringRef(), V, true);
30676e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher  }
30776e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher
308de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  template <typename T> void printObject(StringRef Label, const T &Value) {
309de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    startLine() << Label << ": " << Value << "\n";
31076e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher  }
31176e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher
312de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  raw_ostream &startLine() {
313de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    printIndent();
31476e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher    return OS;
31576e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher  }
31676e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher
317de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  raw_ostream &getOStream() { return OS; }
318de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
31976e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopherprivate:
320de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  template <typename T> void printVersionInternal(T Value) {
321de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    getOStream() << Value;
322de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  }
323de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
324de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  template <typename S, typename T, typename... TArgs>
325de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  void printVersionInternal(S Value, T Value2, TArgs... Args) {
326de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    getOStream() << Value << ".";
327de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    printVersionInternal(Value2, Args...);
328de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  }
329de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
330de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  template <typename T>
331de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  static bool flagName(const EnumEntry<T> &lhs, const EnumEntry<T> &rhs) {
33276e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher    return lhs.Name < rhs.Name;
33376e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher  }
33476e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher
33576e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher  void printBinaryImpl(StringRef Label, StringRef Str, ArrayRef<uint8_t> Value,
33676e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher                       bool Block);
33776e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher
33876e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher  raw_ostream &OS;
33976e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher  int IndentLevel;
340de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  StringRef Prefix;
34176e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher};
34276e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher
343de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainartemplate <>
344de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarinline void
345de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga NainarScopedPrinter::printHex<support::ulittle16_t>(StringRef Label,
346de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar                                              support::ulittle16_t Value) {
347de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  startLine() << Label << ": " << hex(Value) << "\n";
348de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar}
349de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
350de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainartemplate<char Open, char Close>
351de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarstruct DelimitedScope {
352de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  explicit DelimitedScope(ScopedPrinter &W) : W(W) {
353de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    W.startLine() << Open << '\n';
35476e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher    W.indent();
35576e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher  }
35676e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher
357de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  DelimitedScope(ScopedPrinter &W, StringRef N) : W(W) {
358de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    W.startLine() << N;
359de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    if (!N.empty())
360de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar      W.getOStream() << ' ';
361de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    W.getOStream() << Open << '\n';
36276e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher    W.indent();
36376e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher  }
36476e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher
365de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  ~DelimitedScope() {
36676e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher    W.unindent();
367de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar    W.startLine() << Close << '\n';
36876e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher  }
36976e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher
370de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar  ScopedPrinter &W;
37176e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher};
37276e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher
373de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarusing DictScope = DelimitedScope<'{', '}'>;
374de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarusing ListScope = DelimitedScope<'[', ']'>;
375de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar
37676e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher} // namespace llvm
37776e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher
37876e70f340c09ba759ad96d8dfe416b64f24bc287Eric Christopher#endif
379