Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
14 pmbaty 1
//===--- Utility.h -------------------*- mode:c++;eval:(read-only-mode) -*-===//
2
//       Do not edit! See README.txt.
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
//
9
// Provide some utility classes for use in the demangler.
10
// There are two copies of this file in the source tree.  The one in libcxxabi
11
// is the original and the one in llvm is the copy.  Use cp-to-llvm.sh to update
12
// the copy.  See README.txt for more details.
13
//
14
//===----------------------------------------------------------------------===//
15
 
16
#ifndef DEMANGLE_UTILITY_H
17
#define DEMANGLE_UTILITY_H
18
 
19
#include "StringView.h"
20
#include <array>
21
#include <cstdint>
22
#include <cstdlib>
23
#include <cstring>
24
#include <exception>
25
#include <limits>
26
 
27
DEMANGLE_NAMESPACE_BEGIN
28
 
29
// Stream that AST nodes write their string representation into after the AST
30
// has been parsed.
31
class OutputBuffer {
32
  char *Buffer = nullptr;
33
  size_t CurrentPosition = 0;
34
  size_t BufferCapacity = 0;
35
 
36
  // Ensure there are at least N more positions in the buffer.
37
  void grow(size_t N) {
38
    size_t Need = N + CurrentPosition;
39
    if (Need > BufferCapacity) {
40
      // Reduce the number of reallocations, with a bit of hysteresis. The
41
      // number here is chosen so the first allocation will more-than-likely not
42
      // allocate more than 1K.
43
      Need += 1024 - 32;
44
      BufferCapacity *= 2;
45
      if (BufferCapacity < Need)
46
        BufferCapacity = Need;
47
      Buffer = static_cast<char *>(std::realloc(Buffer, BufferCapacity));
48
      if (Buffer == nullptr)
49
        std::terminate();
50
    }
51
  }
52
 
53
  OutputBuffer &writeUnsigned(uint64_t N, bool isNeg = false) {
54
    std::array<char, 21> Temp;
55
    char *TempPtr = Temp.data() + Temp.size();
56
 
57
    // Output at least one character.
58
    do {
59
      *--TempPtr = char('0' + N % 10);
60
      N /= 10;
61
    } while (N);
62
 
63
    // Add negative sign.
64
    if (isNeg)
65
      *--TempPtr = '-';
66
 
67
    return operator+=(StringView(TempPtr, Temp.data() + Temp.size()));
68
  }
69
 
70
public:
71
  OutputBuffer(char *StartBuf, size_t Size)
72
      : Buffer(StartBuf), BufferCapacity(Size) {}
73
  OutputBuffer(char *StartBuf, size_t *SizePtr)
74
      : OutputBuffer(StartBuf, StartBuf ? *SizePtr : 0) {}
75
  OutputBuffer() = default;
76
  // Non-copyable
77
  OutputBuffer(const OutputBuffer &) = delete;
78
  OutputBuffer &operator=(const OutputBuffer &) = delete;
79
 
80
  operator StringView() const { return StringView(Buffer, CurrentPosition); }
81
 
82
  /// If a ParameterPackExpansion (or similar type) is encountered, the offset
83
  /// into the pack that we're currently printing.
84
  unsigned CurrentPackIndex = std::numeric_limits<unsigned>::max();
85
  unsigned CurrentPackMax = std::numeric_limits<unsigned>::max();
86
 
87
  /// When zero, we're printing template args and '>' needs to be parenthesized.
88
  /// Use a counter so we can simply increment inside parentheses.
89
  unsigned GtIsGt = 1;
90
 
91
  bool isGtInsideTemplateArgs() const { return GtIsGt == 0; }
92
 
93
  void printOpen(char Open = '(') {
94
    GtIsGt++;
95
    *this += Open;
96
  }
97
  void printClose(char Close = ')') {
98
    GtIsGt--;
99
    *this += Close;
100
  }
101
 
102
  OutputBuffer &operator+=(StringView R) {
103
    if (size_t Size = R.size()) {
104
      grow(Size);
105
      std::memcpy(Buffer + CurrentPosition, R.begin(), Size);
106
      CurrentPosition += Size;
107
    }
108
    return *this;
109
  }
110
 
111
  OutputBuffer &operator+=(char C) {
112
    grow(1);
113
    Buffer[CurrentPosition++] = C;
114
    return *this;
115
  }
116
 
117
  OutputBuffer &prepend(StringView R) {
118
    size_t Size = R.size();
119
 
120
    grow(Size);
121
    std::memmove(Buffer + Size, Buffer, CurrentPosition);
122
    std::memcpy(Buffer, R.begin(), Size);
123
    CurrentPosition += Size;
124
 
125
    return *this;
126
  }
127
 
128
  OutputBuffer &operator<<(StringView R) { return (*this += R); }
129
 
130
  OutputBuffer &operator<<(char C) { return (*this += C); }
131
 
132
  OutputBuffer &operator<<(long long N) {
133
    return writeUnsigned(static_cast<unsigned long long>(std::abs(N)), N < 0);
134
  }
135
 
136
  OutputBuffer &operator<<(unsigned long long N) {
137
    return writeUnsigned(N, false);
138
  }
139
 
140
  OutputBuffer &operator<<(long N) {
141
    return this->operator<<(static_cast<long long>(N));
142
  }
143
 
144
  OutputBuffer &operator<<(unsigned long N) {
145
    return this->operator<<(static_cast<unsigned long long>(N));
146
  }
147
 
148
  OutputBuffer &operator<<(int N) {
149
    return this->operator<<(static_cast<long long>(N));
150
  }
151
 
152
  OutputBuffer &operator<<(unsigned int N) {
153
    return this->operator<<(static_cast<unsigned long long>(N));
154
  }
155
 
156
  void insert(size_t Pos, const char *S, size_t N) {
157
    assert(Pos <= CurrentPosition);
158
    if (N == 0)
159
      return;
160
    grow(N);
161
    std::memmove(Buffer + Pos + N, Buffer + Pos, CurrentPosition - Pos);
162
    std::memcpy(Buffer + Pos, S, N);
163
    CurrentPosition += N;
164
  }
165
 
166
  size_t getCurrentPosition() const { return CurrentPosition; }
167
  void setCurrentPosition(size_t NewPos) { CurrentPosition = NewPos; }
168
 
169
  char back() const {
170
    assert(CurrentPosition);
171
    return Buffer[CurrentPosition - 1];
172
  }
173
 
174
  bool empty() const { return CurrentPosition == 0; }
175
 
176
  char *getBuffer() { return Buffer; }
177
  char *getBufferEnd() { return Buffer + CurrentPosition - 1; }
178
  size_t getBufferCapacity() const { return BufferCapacity; }
179
};
180
 
181
template <class T> class ScopedOverride {
182
  T &Loc;
183
  T Original;
184
 
185
public:
186
  ScopedOverride(T &Loc_) : ScopedOverride(Loc_, Loc_) {}
187
 
188
  ScopedOverride(T &Loc_, T NewVal) : Loc(Loc_), Original(Loc_) {
189
    Loc_ = std::move(NewVal);
190
  }
191
  ~ScopedOverride() { Loc = std::move(Original); }
192
 
193
  ScopedOverride(const ScopedOverride &) = delete;
194
  ScopedOverride &operator=(const ScopedOverride &) = delete;
195
};
196
 
197
DEMANGLE_NAMESPACE_END
198
 
199
#endif