Coverage Report

Created: 2019-07-24 05:18

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/lib/CodeGen/AsmPrinter/AccelTable.cpp
Line
Count
Source (jump to first uncovered line)
1
//===- llvm/CodeGen/AsmPrinter/AccelTable.cpp - Accelerator Tables --------===//
2
//
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
// This file contains support for writing accelerator tables.
10
//
11
//===----------------------------------------------------------------------===//
12
13
#include "llvm/CodeGen/AccelTable.h"
14
#include "DwarfCompileUnit.h"
15
#include "llvm/ADT/STLExtras.h"
16
#include "llvm/ADT/StringMap.h"
17
#include "llvm/ADT/Twine.h"
18
#include "llvm/BinaryFormat/Dwarf.h"
19
#include "llvm/CodeGen/AsmPrinter.h"
20
#include "llvm/CodeGen/DIE.h"
21
#include "llvm/MC/MCExpr.h"
22
#include "llvm/MC/MCStreamer.h"
23
#include "llvm/MC/MCSymbol.h"
24
#include "llvm/Support/raw_ostream.h"
25
#include "llvm/Target/TargetLoweringObjectFile.h"
26
#include <algorithm>
27
#include <cstddef>
28
#include <cstdint>
29
#include <limits>
30
#include <vector>
31
32
using namespace llvm;
33
34
10.6k
void AccelTableBase::computeBucketCount() {
35
10.6k
  // First get the number of unique hashes.
36
10.6k
  std::vector<uint32_t> Uniques;
37
10.6k
  Uniques.reserve(Entries.size());
38
10.6k
  for (const auto &E : Entries)
39
71.8k
    Uniques.push_back(E.second.HashValue);
40
10.6k
  array_pod_sort(Uniques.begin(), Uniques.end());
41
10.6k
  std::vector<uint32_t>::iterator P =
42
10.6k
      std::unique(Uniques.begin(), Uniques.end());
43
10.6k
44
10.6k
  UniqueHashCount = std::distance(Uniques.begin(), P);
45
10.6k
46
10.6k
  if (UniqueHashCount > 1024)
47
0
    BucketCount = UniqueHashCount / 4;
48
10.6k
  else if (UniqueHashCount > 16)
49
946
    BucketCount = UniqueHashCount / 2;
50
9.74k
  else
51
9.74k
    BucketCount = std::max<uint32_t>(UniqueHashCount, 1);
52
10.6k
}
53
54
10.6k
void AccelTableBase::finalize(AsmPrinter *Asm, StringRef Prefix) {
55
10.6k
  // Create the individual hash data outputs.
56
71.8k
  for (auto &E : Entries) {
57
71.8k
    // Unique the entries.
58
71.8k
    llvm::stable_sort(E.second.Values,
59
345k
                      [](const AccelTableData *A, const AccelTableData *B) {
60
345k
                        return *A < *B;
61
345k
                      });
62
71.8k
    E.second.Values.erase(
63
71.8k
        std::unique(E.second.Values.begin(), E.second.Values.end()),
64
71.8k
        E.second.Values.end());
65
71.8k
  }
66
10.6k
67
10.6k
  // Figure out how many buckets we need, then compute the bucket contents and
68
10.6k
  // the final ordering. The hashes and offsets can be emitted by walking these
69
10.6k
  // data structures. We add temporary symbols to the data so they can be
70
10.6k
  // referenced when emitting the offsets.
71
10.6k
  computeBucketCount();
72
10.6k
73
10.6k
  // Compute bucket contents and final ordering.
74
10.6k
  Buckets.resize(BucketCount);
75
71.8k
  for (auto &E : Entries) {
76
71.8k
    uint32_t Bucket = E.second.HashValue % BucketCount;
77
71.8k
    Buckets[Bucket].push_back(&E.second);
78
71.8k
    E.second.Sym = Asm->createTempSymbol(Prefix);
79
71.8k
  }
80
10.6k
81
10.6k
  // Sort the contents of the buckets by hash value so that hash collisions end
82
10.6k
  // up together. Stable sort makes testing easier and doesn't cost much more.
83
10.6k
  for (auto &Bucket : Buckets)
84
59.4k
    
llvm::stable_sort(Bucket, [](HashData *LHS, HashData *RHS) 47.0k
{
85
59.4k
      return LHS->HashValue < RHS->HashValue;
86
59.4k
    });
87
10.6k
}
88
89
namespace {
90
/// Base class for writing out Accelerator tables. It holds the common
91
/// functionality for the two Accelerator table types.
92
class AccelTableWriter {
93
protected:
94
  AsmPrinter *const Asm;          ///< Destination.
95
  const AccelTableBase &Contents; ///< Data to emit.
96
97
  /// Controls whether to emit duplicate hash and offset table entries for names
98
  /// with identical hashes. Apple tables don't emit duplicate entries, DWARF v5
99
  /// tables do.
100
  const bool SkipIdenticalHashes;
101
102
  void emitHashes() const;
103
104
  /// Emit offsets to lists of entries with identical names. The offsets are
105
  /// relative to the Base argument.
106
  void emitOffsets(const MCSymbol *Base) const;
107
108
public:
109
  AccelTableWriter(AsmPrinter *Asm, const AccelTableBase &Contents,
110
                   bool SkipIdenticalHashes)
111
10.6k
      : Asm(Asm), Contents(Contents), SkipIdenticalHashes(SkipIdenticalHashes) {
112
10.6k
  }
113
};
114
115
class AppleAccelTableWriter : public AccelTableWriter {
116
  using Atom = AppleAccelTableData::Atom;
117
118
  /// The fixed header of an Apple Accelerator Table.
119
  struct Header {
120
    uint32_t Magic = MagicHash;
121
    uint16_t Version = 1;
122
    uint16_t HashFunction = dwarf::DW_hash_function_djb;
123
    uint32_t BucketCount;
124
    uint32_t HashCount;
125
    uint32_t HeaderDataLength;
126
127
    /// 'HASH' magic value to detect endianness.
128
    static const uint32_t MagicHash = 0x48415348;
129
130
    Header(uint32_t BucketCount, uint32_t UniqueHashCount, uint32_t DataLength)
131
        : BucketCount(BucketCount), HashCount(UniqueHashCount),
132
10.6k
          HeaderDataLength(DataLength) {}
133
134
    void emit(AsmPrinter *Asm) const;
135
#ifndef NDEBUG
136
    void print(raw_ostream &OS) const;
137
    void dump() const { print(dbgs()); }
138
#endif
139
  };
140
141
  /// The HeaderData describes the structure of an Apple accelerator table
142
  /// through a list of Atoms.
143
  struct HeaderData {
144
    /// In the case of data that is referenced via DW_FORM_ref_* the offset
145
    /// base is used to describe the offset for all forms in the list of atoms.
146
    uint32_t DieOffsetBase;
147
148
    const SmallVector<Atom, 4> Atoms;
149
150
    HeaderData(ArrayRef<Atom> AtomList, uint32_t Offset = 0)
151
10.6k
        : DieOffsetBase(Offset), Atoms(AtomList.begin(), AtomList.end()) {}
152
153
    void emit(AsmPrinter *Asm) const;
154
#ifndef NDEBUG
155
    void print(raw_ostream &OS) const;
156
    void dump() const { print(dbgs()); }
157
#endif
158
  };
159
160
  Header Header;
161
  HeaderData HeaderData;
162
  const MCSymbol *SecBegin;
163
164
  void emitBuckets() const;
165
  void emitData() const;
166
167
public:
168
  AppleAccelTableWriter(AsmPrinter *Asm, const AccelTableBase &Contents,
169
                        ArrayRef<Atom> Atoms, const MCSymbol *SecBegin)
170
      : AccelTableWriter(Asm, Contents, true),
171
        Header(Contents.getBucketCount(), Contents.getUniqueHashCount(),
172
               8 + (Atoms.size() * 4)),
173
10.6k
        HeaderData(Atoms), SecBegin(SecBegin) {}
174
175
  void emit() const;
176
177
#ifndef NDEBUG
178
  void print(raw_ostream &OS) const;
179
  void dump() const { print(dbgs()); }
180
#endif
181
};
182
183
/// Class responsible for emitting a DWARF v5 Accelerator Table. The only
184
/// public function is emit(), which performs the actual emission.
185
///
186
/// The class is templated in its data type. This allows us to emit both dyamic
187
/// and static data entries. A callback abstract the logic to provide a CU
188
/// index for a given entry, which is different per data type, but identical
189
/// for every entry in the same table.
190
template <typename DataT>
191
class Dwarf5AccelTableWriter : public AccelTableWriter {
192
  struct Header {
193
    uint32_t UnitLength = 0;
194
    uint16_t Version = 5;
195
    uint16_t Padding = 0;
196
    uint32_t CompUnitCount;
197
    uint32_t LocalTypeUnitCount = 0;
198
    uint32_t ForeignTypeUnitCount = 0;
199
    uint32_t BucketCount;
200
    uint32_t NameCount;
201
    uint32_t AbbrevTableSize = 0;
202
    uint32_t AugmentationStringSize = sizeof(AugmentationString);
203
    char AugmentationString[8] = {'L', 'L', 'V', 'M', '0', '7', '0', '0'};
204
205
    Header(uint32_t CompUnitCount, uint32_t BucketCount, uint32_t NameCount)
206
        : CompUnitCount(CompUnitCount), BucketCount(BucketCount),
207
63
          NameCount(NameCount) {}
AccelTable.cpp:(anonymous namespace)::Dwarf5AccelTableWriter<llvm::DWARF5AccelTableData>::Header::Header(unsigned int, unsigned int, unsigned int)
Line
Count
Source
207
61
          NameCount(NameCount) {}
AccelTable.cpp:(anonymous namespace)::Dwarf5AccelTableWriter<llvm::DWARF5AccelTableStaticData>::Header::Header(unsigned int, unsigned int, unsigned int)
Line
Count
Source
207
2
          NameCount(NameCount) {}
208
209
    void emit(const Dwarf5AccelTableWriter &Ctx) const;
210
  };
211
  struct AttributeEncoding {
212
    dwarf::Index Index;
213
    dwarf::Form Form;
214
  };
215
216
  Header Header;
217
  DenseMap<uint32_t, SmallVector<AttributeEncoding, 2>> Abbreviations;
218
  ArrayRef<MCSymbol *> CompUnits;
219
  llvm::function_ref<unsigned(const DataT &)> getCUIndexForEntry;
220
  MCSymbol *ContributionStart = Asm->createTempSymbol("names_start");
221
  MCSymbol *ContributionEnd = Asm->createTempSymbol("names_end");
222
  MCSymbol *AbbrevStart = Asm->createTempSymbol("names_abbrev_start");
223
  MCSymbol *AbbrevEnd = Asm->createTempSymbol("names_abbrev_end");
224
  MCSymbol *EntryPool = Asm->createTempSymbol("names_entries");
225
226
  DenseSet<uint32_t> getUniqueTags() const;
227
228
  // Right now, we emit uniform attributes for all tags.
229
  SmallVector<AttributeEncoding, 2> getUniformAttributes() const;
230
231
  void emitCUList() const;
232
  void emitBuckets() const;
233
  void emitStringOffsets() const;
234
  void emitAbbrevs() const;
235
  void emitEntry(const DataT &Entry) const;
236
  void emitData() const;
237
238
public:
239
  Dwarf5AccelTableWriter(
240
      AsmPrinter *Asm, const AccelTableBase &Contents,
241
      ArrayRef<MCSymbol *> CompUnits,
242
      llvm::function_ref<unsigned(const DataT &)> GetCUIndexForEntry);
243
244
  void emit() const;
245
};
246
} // namespace
247
248
10.6k
void AccelTableWriter::emitHashes() const {
249
10.6k
  uint64_t PrevHash = std::numeric_limits<uint64_t>::max();
250
10.6k
  unsigned BucketIdx = 0;
251
47.0k
  for (auto &Bucket : Contents.getBuckets()) {
252
71.8k
    for (auto &Hash : Bucket) {
253
71.8k
      uint32_t HashValue = Hash->HashValue;
254
71.8k
      if (SkipIdenticalHashes && 
PrevHash == HashValue71.3k
)
255
6
        continue;
256
71.8k
      Asm->OutStreamer->AddComment("Hash in Bucket " + Twine(BucketIdx));
257
71.8k
      Asm->emitInt32(HashValue);
258
71.8k
      PrevHash = HashValue;
259
71.8k
    }
260
47.0k
    BucketIdx++;
261
47.0k
  }
262
10.6k
}
263
264
10.6k
void AccelTableWriter::emitOffsets(const MCSymbol *Base) const {
265
10.6k
  const auto &Buckets = Contents.getBuckets();
266
10.6k
  uint64_t PrevHash = std::numeric_limits<uint64_t>::max();
267
57.7k
  for (size_t i = 0, e = Buckets.size(); i < e; 
++i47.0k
) {
268
71.8k
    for (auto *Hash : Buckets[i]) {
269
71.8k
      uint32_t HashValue = Hash->HashValue;
270
71.8k
      if (SkipIdenticalHashes && 
PrevHash == HashValue71.3k
)
271
6
        continue;
272
71.8k
      PrevHash = HashValue;
273
71.8k
      Asm->OutStreamer->AddComment("Offset in Bucket " + Twine(i));
274
71.8k
      Asm->EmitLabelDifference(Hash->Sym, Base, sizeof(uint32_t));
275
71.8k
    }
276
47.0k
  }
277
10.6k
}
278
279
10.6k
void AppleAccelTableWriter::Header::emit(AsmPrinter *Asm) const {
280
10.6k
  Asm->OutStreamer->AddComment("Header Magic");
281
10.6k
  Asm->emitInt32(Magic);
282
10.6k
  Asm->OutStreamer->AddComment("Header Version");
283
10.6k
  Asm->emitInt16(Version);
284
10.6k
  Asm->OutStreamer->AddComment("Header Hash Function");
285
10.6k
  Asm->emitInt16(HashFunction);
286
10.6k
  Asm->OutStreamer->AddComment("Header Bucket Count");
287
10.6k
  Asm->emitInt32(BucketCount);
288
10.6k
  Asm->OutStreamer->AddComment("Header Hash Count");
289
10.6k
  Asm->emitInt32(HashCount);
290
10.6k
  Asm->OutStreamer->AddComment("Header Data Length");
291
10.6k
  Asm->emitInt32(HeaderDataLength);
292
10.6k
}
293
294
10.6k
void AppleAccelTableWriter::HeaderData::emit(AsmPrinter *Asm) const {
295
10.6k
  Asm->OutStreamer->AddComment("HeaderData Die Offset Base");
296
10.6k
  Asm->emitInt32(DieOffsetBase);
297
10.6k
  Asm->OutStreamer->AddComment("HeaderData Atom Count");
298
10.6k
  Asm->emitInt32(Atoms.size());
299
10.6k
300
16.0k
  for (const Atom &A : Atoms) {
301
16.0k
    Asm->OutStreamer->AddComment(dwarf::AtomTypeString(A.Type));
302
16.0k
    Asm->emitInt16(A.Type);
303
16.0k
    Asm->OutStreamer->AddComment(dwarf::FormEncodingString(A.Form));
304
16.0k
    Asm->emitInt16(A.Form);
305
16.0k
  }
306
10.6k
}
307
308
10.6k
void AppleAccelTableWriter::emitBuckets() const {
309
10.6k
  const auto &Buckets = Contents.getBuckets();
310
10.6k
  unsigned index = 0;
311
57.3k
  for (size_t i = 0, e = Buckets.size(); i < e; 
++i46.7k
) {
312
46.7k
    Asm->OutStreamer->AddComment("Bucket " + Twine(i));
313
46.7k
    if (!Buckets[i].empty())
314
32.1k
      Asm->emitInt32(index);
315
14.6k
    else
316
14.6k
      Asm->emitInt32(std::numeric_limits<uint32_t>::max());
317
46.7k
    // Buckets point in the list of hashes, not to the data. Do not increment
318
46.7k
    // the index multiple times in case of hash collisions.
319
46.7k
    uint64_t PrevHash = std::numeric_limits<uint64_t>::max();
320
71.3k
    for (auto *HD : Buckets[i]) {
321
71.3k
      uint32_t HashValue = HD->HashValue;
322
71.3k
      if (PrevHash != HashValue)
323
71.3k
        ++index;
324
71.3k
      PrevHash = HashValue;
325
71.3k
    }
326
46.7k
  }
327
10.6k
}
328
329
10.6k
void AppleAccelTableWriter::emitData() const {
330
10.6k
  const auto &Buckets = Contents.getBuckets();
331
57.3k
  for (size_t i = 0, e = Buckets.size(); i < e; 
++i46.7k
) {
332
46.7k
    uint64_t PrevHash = std::numeric_limits<uint64_t>::max();
333
71.3k
    for (auto &Hash : Buckets[i]) {
334
71.3k
      // Terminate the previous entry if there is no hash collision with the
335
71.3k
      // current one.
336
71.3k
      if (PrevHash != std::numeric_limits<uint64_t>::max() &&
337
71.3k
          
PrevHash != Hash->HashValue39.2k
)
338
39.2k
        Asm->emitInt32(0);
339
71.3k
      // Remember to emit the label for our offset.
340
71.3k
      Asm->OutStreamer->EmitLabel(Hash->Sym);
341
71.3k
      Asm->OutStreamer->AddComment(Hash->Name.getString());
342
71.3k
      Asm->emitDwarfStringOffset(Hash->Name);
343
71.3k
      Asm->OutStreamer->AddComment("Num DIEs");
344
71.3k
      Asm->emitInt32(Hash->Values.size());
345
71.3k
      for (const auto *V : Hash->Values)
346
316k
        static_cast<const AppleAccelTableData *>(V)->emit(Asm);
347
71.3k
      PrevHash = Hash->HashValue;
348
71.3k
    }
349
46.7k
    // Emit the final end marker for the bucket.
350
46.7k
    if (!Buckets[i].empty())
351
32.1k
      Asm->emitInt32(0);
352
46.7k
  }
353
10.6k
}
354
355
10.6k
void AppleAccelTableWriter::emit() const {
356
10.6k
  Header.emit(Asm);
357
10.6k
  HeaderData.emit(Asm);
358
10.6k
  emitBuckets();
359
10.6k
  emitHashes();
360
10.6k
  emitOffsets(SecBegin);
361
10.6k
  emitData();
362
10.6k
}
363
364
template <typename DataT>
365
void Dwarf5AccelTableWriter<DataT>::Header::emit(
366
63
    const Dwarf5AccelTableWriter &Ctx) const {
367
63
  assert(CompUnitCount > 0 && "Index must have at least one CU.");
368
63
369
63
  AsmPrinter *Asm = Ctx.Asm;
370
63
  Asm->OutStreamer->AddComment("Header: unit length");
371
63
  Asm->EmitLabelDifference(Ctx.ContributionEnd, Ctx.ContributionStart,
372
63
                           sizeof(uint32_t));
373
63
  Asm->OutStreamer->EmitLabel(Ctx.ContributionStart);
374
63
  Asm->OutStreamer->AddComment("Header: version");
375
63
  Asm->emitInt16(Version);
376
63
  Asm->OutStreamer->AddComment("Header: padding");
377
63
  Asm->emitInt16(Padding);
378
63
  Asm->OutStreamer->AddComment("Header: compilation unit count");
379
63
  Asm->emitInt32(CompUnitCount);
380
63
  Asm->OutStreamer->AddComment("Header: local type unit count");
381
63
  Asm->emitInt32(LocalTypeUnitCount);
382
63
  Asm->OutStreamer->AddComment("Header: foreign type unit count");
383
63
  Asm->emitInt32(ForeignTypeUnitCount);
384
63
  Asm->OutStreamer->AddComment("Header: bucket count");
385
63
  Asm->emitInt32(BucketCount);
386
63
  Asm->OutStreamer->AddComment("Header: name count");
387
63
  Asm->emitInt32(NameCount);
388
63
  Asm->OutStreamer->AddComment("Header: abbreviation table size");
389
63
  Asm->EmitLabelDifference(Ctx.AbbrevEnd, Ctx.AbbrevStart, sizeof(uint32_t));
390
63
  Asm->OutStreamer->AddComment("Header: augmentation string size");
391
63
  assert(AugmentationStringSize % 4 == 0);
392
63
  Asm->emitInt32(AugmentationStringSize);
393
63
  Asm->OutStreamer->AddComment("Header: augmentation string");
394
63
  Asm->OutStreamer->EmitBytes({AugmentationString, AugmentationStringSize});
395
63
}
AccelTable.cpp:(anonymous namespace)::Dwarf5AccelTableWriter<llvm::DWARF5AccelTableData>::Header::emit((anonymous namespace)::Dwarf5AccelTableWriter<llvm::DWARF5AccelTableData> const&) const
Line
Count
Source
366
61
    const Dwarf5AccelTableWriter &Ctx) const {
367
61
  assert(CompUnitCount > 0 && "Index must have at least one CU.");
368
61
369
61
  AsmPrinter *Asm = Ctx.Asm;
370
61
  Asm->OutStreamer->AddComment("Header: unit length");
371
61
  Asm->EmitLabelDifference(Ctx.ContributionEnd, Ctx.ContributionStart,
372
61
                           sizeof(uint32_t));
373
61
  Asm->OutStreamer->EmitLabel(Ctx.ContributionStart);
374
61
  Asm->OutStreamer->AddComment("Header: version");
375
61
  Asm->emitInt16(Version);
376
61
  Asm->OutStreamer->AddComment("Header: padding");
377
61
  Asm->emitInt16(Padding);
378
61
  Asm->OutStreamer->AddComment("Header: compilation unit count");
379
61
  Asm->emitInt32(CompUnitCount);
380
61
  Asm->OutStreamer->AddComment("Header: local type unit count");
381
61
  Asm->emitInt32(LocalTypeUnitCount);
382
61
  Asm->OutStreamer->AddComment("Header: foreign type unit count");
383
61
  Asm->emitInt32(ForeignTypeUnitCount);
384
61
  Asm->OutStreamer->AddComment("Header: bucket count");
385
61
  Asm->emitInt32(BucketCount);
386
61
  Asm->OutStreamer->AddComment("Header: name count");
387
61
  Asm->emitInt32(NameCount);
388
61
  Asm->OutStreamer->AddComment("Header: abbreviation table size");
389
61
  Asm->EmitLabelDifference(Ctx.AbbrevEnd, Ctx.AbbrevStart, sizeof(uint32_t));
390
61
  Asm->OutStreamer->AddComment("Header: augmentation string size");
391
61
  assert(AugmentationStringSize % 4 == 0);
392
61
  Asm->emitInt32(AugmentationStringSize);
393
61
  Asm->OutStreamer->AddComment("Header: augmentation string");
394
61
  Asm->OutStreamer->EmitBytes({AugmentationString, AugmentationStringSize});
395
61
}
AccelTable.cpp:(anonymous namespace)::Dwarf5AccelTableWriter<llvm::DWARF5AccelTableStaticData>::Header::emit((anonymous namespace)::Dwarf5AccelTableWriter<llvm::DWARF5AccelTableStaticData> const&) const
Line
Count
Source
366
2
    const Dwarf5AccelTableWriter &Ctx) const {
367
2
  assert(CompUnitCount > 0 && "Index must have at least one CU.");
368
2
369
2
  AsmPrinter *Asm = Ctx.Asm;
370
2
  Asm->OutStreamer->AddComment("Header: unit length");
371
2
  Asm->EmitLabelDifference(Ctx.ContributionEnd, Ctx.ContributionStart,
372
2
                           sizeof(uint32_t));
373
2
  Asm->OutStreamer->EmitLabel(Ctx.ContributionStart);
374
2
  Asm->OutStreamer->AddComment("Header: version");
375
2
  Asm->emitInt16(Version);
376
2
  Asm->OutStreamer->AddComment("Header: padding");
377
2
  Asm->emitInt16(Padding);
378
2
  Asm->OutStreamer->AddComment("Header: compilation unit count");
379
2
  Asm->emitInt32(CompUnitCount);
380
2
  Asm->OutStreamer->AddComment("Header: local type unit count");
381
2
  Asm->emitInt32(LocalTypeUnitCount);
382
2
  Asm->OutStreamer->AddComment("Header: foreign type unit count");
383
2
  Asm->emitInt32(ForeignTypeUnitCount);
384
2
  Asm->OutStreamer->AddComment("Header: bucket count");
385
2
  Asm->emitInt32(BucketCount);
386
2
  Asm->OutStreamer->AddComment("Header: name count");
387
2
  Asm->emitInt32(NameCount);
388
2
  Asm->OutStreamer->AddComment("Header: abbreviation table size");
389
2
  Asm->EmitLabelDifference(Ctx.AbbrevEnd, Ctx.AbbrevStart, sizeof(uint32_t));
390
2
  Asm->OutStreamer->AddComment("Header: augmentation string size");
391
2
  assert(AugmentationStringSize % 4 == 0);
392
2
  Asm->emitInt32(AugmentationStringSize);
393
2
  Asm->OutStreamer->AddComment("Header: augmentation string");
394
2
  Asm->OutStreamer->EmitBytes({AugmentationString, AugmentationStringSize});
395
2
}
396
397
template <typename DataT>
398
63
DenseSet<uint32_t> Dwarf5AccelTableWriter<DataT>::getUniqueTags() const {
399
63
  DenseSet<uint32_t> UniqueTags;
400
331
  for (auto &Bucket : Contents.getBuckets()) {
401
466
    for (auto *Hash : Bucket) {
402
480
      for (auto *Value : Hash->Values) {
403
480
        unsigned Tag = static_cast<const DataT *>(Value)->getDieTag();
404
480
        UniqueTags.insert(Tag);
405
480
      }
406
466
    }
407
331
  }
408
63
  return UniqueTags;
409
63
}
AccelTable.cpp:(anonymous namespace)::Dwarf5AccelTableWriter<llvm::DWARF5AccelTableData>::getUniqueTags() const
Line
Count
Source
398
61
DenseSet<uint32_t> Dwarf5AccelTableWriter<DataT>::getUniqueTags() const {
399
61
  DenseSet<uint32_t> UniqueTags;
400
313
  for (auto &Bucket : Contents.getBuckets()) {
401
448
    for (auto *Hash : Bucket) {
402
456
      for (auto *Value : Hash->Values) {
403
456
        unsigned Tag = static_cast<const DataT *>(Value)->getDieTag();
404
456
        UniqueTags.insert(Tag);
405
456
      }
406
448
    }
407
313
  }
408
61
  return UniqueTags;
409
61
}
AccelTable.cpp:(anonymous namespace)::Dwarf5AccelTableWriter<llvm::DWARF5AccelTableStaticData>::getUniqueTags() const
Line
Count
Source
398
2
DenseSet<uint32_t> Dwarf5AccelTableWriter<DataT>::getUniqueTags() const {
399
2
  DenseSet<uint32_t> UniqueTags;
400
18
  for (auto &Bucket : Contents.getBuckets()) {
401
18
    for (auto *Hash : Bucket) {
402
24
      for (auto *Value : Hash->Values) {
403
24
        unsigned Tag = static_cast<const DataT *>(Value)->getDieTag();
404
24
        UniqueTags.insert(Tag);
405
24
      }
406
18
    }
407
18
  }
408
2
  return UniqueTags;
409
2
}
410
411
template <typename DataT>
412
SmallVector<typename Dwarf5AccelTableWriter<DataT>::AttributeEncoding, 2>
413
63
Dwarf5AccelTableWriter<DataT>::getUniformAttributes() const {
414
63
  SmallVector<AttributeEncoding, 2> UA;
415
63
  if (CompUnits.size() > 1) {
416
7
    size_t LargestCUIndex = CompUnits.size() - 1;
417
7
    dwarf::Form Form = DIEInteger::BestForm(/*IsSigned*/ false, LargestCUIndex);
418
7
    UA.push_back({dwarf::DW_IDX_compile_unit, Form});
419
7
  }
420
63
  UA.push_back({dwarf::DW_IDX_die_offset, dwarf::DW_FORM_ref4});
421
63
  return UA;
422
63
}
AccelTable.cpp:(anonymous namespace)::Dwarf5AccelTableWriter<llvm::DWARF5AccelTableData>::getUniformAttributes() const
Line
Count
Source
413
61
Dwarf5AccelTableWriter<DataT>::getUniformAttributes() const {
414
61
  SmallVector<AttributeEncoding, 2> UA;
415
61
  if (CompUnits.size() > 1) {
416
5
    size_t LargestCUIndex = CompUnits.size() - 1;
417
5
    dwarf::Form Form = DIEInteger::BestForm(/*IsSigned*/ false, LargestCUIndex);
418
5
    UA.push_back({dwarf::DW_IDX_compile_unit, Form});
419
5
  }
420
61
  UA.push_back({dwarf::DW_IDX_die_offset, dwarf::DW_FORM_ref4});
421
61
  return UA;
422
61
}
AccelTable.cpp:(anonymous namespace)::Dwarf5AccelTableWriter<llvm::DWARF5AccelTableStaticData>::getUniformAttributes() const
Line
Count
Source
413
2
Dwarf5AccelTableWriter<DataT>::getUniformAttributes() const {
414
2
  SmallVector<AttributeEncoding, 2> UA;
415
2
  if (CompUnits.size() > 1) {
416
2
    size_t LargestCUIndex = CompUnits.size() - 1;
417
2
    dwarf::Form Form = DIEInteger::BestForm(/*IsSigned*/ false, LargestCUIndex);
418
2
    UA.push_back({dwarf::DW_IDX_compile_unit, Form});
419
2
  }
420
2
  UA.push_back({dwarf::DW_IDX_die_offset, dwarf::DW_FORM_ref4});
421
2
  return UA;
422
2
}
423
424
template <typename DataT>
425
63
void Dwarf5AccelTableWriter<DataT>::emitCUList() const {
426
329
  for (const auto &CU : enumerate(CompUnits)) {
427
329
    Asm->OutStreamer->AddComment("Compilation unit " + Twine(CU.index()));
428
329
    Asm->emitDwarfSymbolReference(CU.value());
429
329
  }
430
63
}
AccelTable.cpp:(anonymous namespace)::Dwarf5AccelTableWriter<llvm::DWARF5AccelTableData>::emitCUList() const
Line
Count
Source
425
61
void Dwarf5AccelTableWriter<DataT>::emitCUList() const {
426
323
  for (const auto &CU : enumerate(CompUnits)) {
427
323
    Asm->OutStreamer->AddComment("Compilation unit " + Twine(CU.index()));
428
323
    Asm->emitDwarfSymbolReference(CU.value());
429
323
  }
430
61
}
AccelTable.cpp:(anonymous namespace)::Dwarf5AccelTableWriter<llvm::DWARF5AccelTableStaticData>::emitCUList() const
Line
Count
Source
425
2
void Dwarf5AccelTableWriter<DataT>::emitCUList() const {
426
6
  for (const auto &CU : enumerate(CompUnits)) {
427
6
    Asm->OutStreamer->AddComment("Compilation unit " + Twine(CU.index()));
428
6
    Asm->emitDwarfSymbolReference(CU.value());
429
6
  }
430
2
}
431
432
template <typename DataT>
433
63
void Dwarf5AccelTableWriter<DataT>::emitBuckets() const {
434
63
  uint32_t Index = 1;
435
331
  for (const auto &Bucket : enumerate(Contents.getBuckets())) {
436
331
    Asm->OutStreamer->AddComment("Bucket " + Twine(Bucket.index()));
437
331
    Asm->emitInt32(Bucket.value().empty() ? 
058
:
Index273
);
438
331
    Index += Bucket.value().size();
439
331
  }
440
63
}
AccelTable.cpp:(anonymous namespace)::Dwarf5AccelTableWriter<llvm::DWARF5AccelTableData>::emitBuckets() const
Line
Count
Source
433
61
void Dwarf5AccelTableWriter<DataT>::emitBuckets() const {
434
61
  uint32_t Index = 1;
435
313
  for (const auto &Bucket : enumerate(Contents.getBuckets())) {
436
313
    Asm->OutStreamer->AddComment("Bucket " + Twine(Bucket.index()));
437
313
    Asm->emitInt32(Bucket.value().empty() ? 
052
:
Index261
);
438
313
    Index += Bucket.value().size();
439
313
  }
440
61
}
AccelTable.cpp:(anonymous namespace)::Dwarf5AccelTableWriter<llvm::DWARF5AccelTableStaticData>::emitBuckets() const
Line
Count
Source
433
2
void Dwarf5AccelTableWriter<DataT>::emitBuckets() const {
434
2
  uint32_t Index = 1;
435
18
  for (const auto &Bucket : enumerate(Contents.getBuckets())) {
436
18
    Asm->OutStreamer->AddComment("Bucket " + Twine(Bucket.index()));
437
18
    Asm->emitInt32(Bucket.value().empty() ? 
06
:
Index12
);
438
18
    Index += Bucket.value().size();
439
18
  }
440
2
}
441
442
template <typename DataT>
443
63
void Dwarf5AccelTableWriter<DataT>::emitStringOffsets() const {
444
331
  for (const auto &Bucket : enumerate(Contents.getBuckets())) {
445
466
    for (auto *Hash : Bucket.value()) {
446
466
      DwarfStringPoolEntryRef String = Hash->Name;
447
466
      Asm->OutStreamer->AddComment("String in Bucket " + Twine(Bucket.index()) +
448
466
                                   ": " + String.getString());
449
466
      Asm->emitDwarfStringOffset(String);
450
466
    }
451
331
  }
452
63
}
AccelTable.cpp:(anonymous namespace)::Dwarf5AccelTableWriter<llvm::DWARF5AccelTableData>::emitStringOffsets() const
Line
Count
Source
443
61
void Dwarf5AccelTableWriter<DataT>::emitStringOffsets() const {
444
313
  for (const auto &Bucket : enumerate(Contents.getBuckets())) {
445
448
    for (auto *Hash : Bucket.value()) {
446
448
      DwarfStringPoolEntryRef String = Hash->Name;
447
448
      Asm->OutStreamer->AddComment("String in Bucket " + Twine(Bucket.index()) +
448
448
                                   ": " + String.getString());
449
448
      Asm->emitDwarfStringOffset(String);
450
448
    }
451
313
  }
452
61
}
AccelTable.cpp:(anonymous namespace)::Dwarf5AccelTableWriter<llvm::DWARF5AccelTableStaticData>::emitStringOffsets() const
Line
Count
Source
443
2
void Dwarf5AccelTableWriter<DataT>::emitStringOffsets() const {
444
18
  for (const auto &Bucket : enumerate(Contents.getBuckets())) {
445
18
    for (auto *Hash : Bucket.value()) {
446
18
      DwarfStringPoolEntryRef String = Hash->Name;
447
18
      Asm->OutStreamer->AddComment("String in Bucket " + Twine(Bucket.index()) +
448
18
                                   ": " + String.getString());
449
18
      Asm->emitDwarfStringOffset(String);
450
18
    }
451
18
  }
452
2
}
453
454
template <typename DataT>
455
63
void Dwarf5AccelTableWriter<DataT>::emitAbbrevs() const {
456
63
  Asm->OutStreamer->EmitLabel(AbbrevStart);
457
134
  for (const auto &Abbrev : Abbreviations) {
458
134
    Asm->OutStreamer->AddComment("Abbrev code");
459
134
    assert(Abbrev.first != 0);
460
134
    Asm->EmitULEB128(Abbrev.first);
461
134
    Asm->OutStreamer->AddComment(dwarf::TagString(Abbrev.first));
462
134
    Asm->EmitULEB128(Abbrev.first);
463
147
    for (const auto &AttrEnc : Abbrev.second) {
464
147
      Asm->EmitULEB128(AttrEnc.Index, dwarf::IndexString(AttrEnc.Index).data());
465
147
      Asm->EmitULEB128(AttrEnc.Form,
466
147
                       dwarf::FormEncodingString(AttrEnc.Form).data());
467
147
    }
468
134
    Asm->EmitULEB128(0, "End of abbrev");
469
134
    Asm->EmitULEB128(0, "End of abbrev");
470
134
  }
471
63
  Asm->EmitULEB128(0, "End of abbrev list");
472
63
  Asm->OutStreamer->EmitLabel(AbbrevEnd);
473
63
}
AccelTable.cpp:(anonymous namespace)::Dwarf5AccelTableWriter<llvm::DWARF5AccelTableData>::emitAbbrevs() const
Line
Count
Source
455
61
void Dwarf5AccelTableWriter<DataT>::emitAbbrevs() const {
456
61
  Asm->OutStreamer->EmitLabel(AbbrevStart);
457
128
  for (const auto &Abbrev : Abbreviations) {
458
128
    Asm->OutStreamer->AddComment("Abbrev code");
459
128
    assert(Abbrev.first != 0);
460
128
    Asm->EmitULEB128(Abbrev.first);
461
128
    Asm->OutStreamer->AddComment(dwarf::TagString(Abbrev.first));
462
128
    Asm->EmitULEB128(Abbrev.first);
463
135
    for (const auto &AttrEnc : Abbrev.second) {
464
135
      Asm->EmitULEB128(AttrEnc.Index, dwarf::IndexString(AttrEnc.Index).data());
465
135
      Asm->EmitULEB128(AttrEnc.Form,
466
135
                       dwarf::FormEncodingString(AttrEnc.Form).data());
467
135
    }
468
128
    Asm->EmitULEB128(0, "End of abbrev");
469
128
    Asm->EmitULEB128(0, "End of abbrev");
470
128
  }
471
61
  Asm->EmitULEB128(0, "End of abbrev list");
472
61
  Asm->OutStreamer->EmitLabel(AbbrevEnd);
473
61
}
AccelTable.cpp:(anonymous namespace)::Dwarf5AccelTableWriter<llvm::DWARF5AccelTableStaticData>::emitAbbrevs() const
Line
Count
Source
455
2
void Dwarf5AccelTableWriter<DataT>::emitAbbrevs() const {
456
2
  Asm->OutStreamer->EmitLabel(AbbrevStart);
457
6
  for (const auto &Abbrev : Abbreviations) {
458
6
    Asm->OutStreamer->AddComment("Abbrev code");
459
6
    assert(Abbrev.first != 0);
460
6
    Asm->EmitULEB128(Abbrev.first);
461
6
    Asm->OutStreamer->AddComment(dwarf::TagString(Abbrev.first));
462
6
    Asm->EmitULEB128(Abbrev.first);
463
12
    for (const auto &AttrEnc : Abbrev.second) {
464
12
      Asm->EmitULEB128(AttrEnc.Index, dwarf::IndexString(AttrEnc.Index).data());
465
12
      Asm->EmitULEB128(AttrEnc.Form,
466
12
                       dwarf::FormEncodingString(AttrEnc.Form).data());
467
12
    }
468
6
    Asm->EmitULEB128(0, "End of abbrev");
469
6
    Asm->EmitULEB128(0, "End of abbrev");
470
6
  }
471
2
  Asm->EmitULEB128(0, "End of abbrev list");
472
2
  Asm->OutStreamer->EmitLabel(AbbrevEnd);
473
2
}
474
475
template <typename DataT>
476
480
void Dwarf5AccelTableWriter<DataT>::emitEntry(const DataT &Entry) const {
477
480
  auto AbbrevIt = Abbreviations.find(Entry.getDieTag());
478
480
  assert(AbbrevIt != Abbreviations.end() &&
479
480
         "Why wasn't this abbrev generated?");
480
480
481
480
  Asm->EmitULEB128(AbbrevIt->first, "Abbreviation code");
482
779
  for (const auto &AttrEnc : AbbrevIt->second) {
483
779
    Asm->OutStreamer->AddComment(dwarf::IndexString(AttrEnc.Index));
484
779
    switch (AttrEnc.Index) {
485
779
    case dwarf::DW_IDX_compile_unit: {
486
299
      DIEInteger ID(getCUIndexForEntry(Entry));
487
299
      ID.EmitValue(Asm, AttrEnc.Form);
488
299
      break;
489
779
    }
490
779
    case dwarf::DW_IDX_die_offset:
491
480
      assert(AttrEnc.Form == dwarf::DW_FORM_ref4);
492
480
      Asm->emitInt32(Entry.getDieOffset());
493
480
      break;
494
779
    default:
495
0
      llvm_unreachable("Unexpected index attribute!");
496
779
    }
497
779
  }
498
480
}
AccelTable.cpp:(anonymous namespace)::Dwarf5AccelTableWriter<llvm::DWARF5AccelTableData>::emitEntry(llvm::DWARF5AccelTableData const&) const
Line
Count
Source
476
456
void Dwarf5AccelTableWriter<DataT>::emitEntry(const DataT &Entry) const {
477
456
  auto AbbrevIt = Abbreviations.find(Entry.getDieTag());
478
456
  assert(AbbrevIt != Abbreviations.end() &&
479
456
         "Why wasn't this abbrev generated?");
480
456
481
456
  Asm->EmitULEB128(AbbrevIt->first, "Abbreviation code");
482
731
  for (const auto &AttrEnc : AbbrevIt->second) {
483
731
    Asm->OutStreamer->AddComment(dwarf::IndexString(AttrEnc.Index));
484
731
    switch (AttrEnc.Index) {
485
731
    case dwarf::DW_IDX_compile_unit: {
486
275
      DIEInteger ID(getCUIndexForEntry(Entry));
487
275
      ID.EmitValue(Asm, AttrEnc.Form);
488
275
      break;
489
731
    }
490
731
    case dwarf::DW_IDX_die_offset:
491
456
      assert(AttrEnc.Form == dwarf::DW_FORM_ref4);
492
456
      Asm->emitInt32(Entry.getDieOffset());
493
456
      break;
494
731
    default:
495
0
      llvm_unreachable("Unexpected index attribute!");
496
731
    }
497
731
  }
498
456
}
AccelTable.cpp:(anonymous namespace)::Dwarf5AccelTableWriter<llvm::DWARF5AccelTableStaticData>::emitEntry(llvm::DWARF5AccelTableStaticData const&) const
Line
Count
Source
476
24
void Dwarf5AccelTableWriter<DataT>::emitEntry(const DataT &Entry) const {
477
24
  auto AbbrevIt = Abbreviations.find(Entry.getDieTag());
478
24
  assert(AbbrevIt != Abbreviations.end() &&
479
24
         "Why wasn't this abbrev generated?");
480
24
481
24
  Asm->EmitULEB128(AbbrevIt->first, "Abbreviation code");
482
48
  for (const auto &AttrEnc : AbbrevIt->second) {
483
48
    Asm->OutStreamer->AddComment(dwarf::IndexString(AttrEnc.Index));
484
48
    switch (AttrEnc.Index) {
485
48
    case dwarf::DW_IDX_compile_unit: {
486
24
      DIEInteger ID(getCUIndexForEntry(Entry));
487
24
      ID.EmitValue(Asm, AttrEnc.Form);
488
24
      break;
489
48
    }
490
48
    case dwarf::DW_IDX_die_offset:
491
24
      assert(AttrEnc.Form == dwarf::DW_FORM_ref4);
492
24
      Asm->emitInt32(Entry.getDieOffset());
493
24
      break;
494
48
    default:
495
0
      llvm_unreachable("Unexpected index attribute!");
496
48
    }
497
48
  }
498
24
}
499
500
63
template <typename DataT> void Dwarf5AccelTableWriter<DataT>::emitData() const {
501
63
  Asm->OutStreamer->EmitLabel(EntryPool);
502
331
  for (auto &Bucket : Contents.getBuckets()) {
503
466
    for (auto *Hash : Bucket) {
504
466
      // Remember to emit the label for our offset.
505
466
      Asm->OutStreamer->EmitLabel(Hash->Sym);
506
466
      for (const auto *Value : Hash->Values)
507
480
        emitEntry(*static_cast<const DataT *>(Value));
508
466
      Asm->OutStreamer->AddComment("End of list: " + Hash->Name.getString());
509
466
      Asm->emitInt32(0);
510
466
    }
511
331
  }
512
63
}
AccelTable.cpp:(anonymous namespace)::Dwarf5AccelTableWriter<llvm::DWARF5AccelTableData>::emitData() const
Line
Count
Source
500
61
template <typename DataT> void Dwarf5AccelTableWriter<DataT>::emitData() const {
501
61
  Asm->OutStreamer->EmitLabel(EntryPool);
502
313
  for (auto &Bucket : Contents.getBuckets()) {
503
448
    for (auto *Hash : Bucket) {
504
448
      // Remember to emit the label for our offset.
505
448
      Asm->OutStreamer->EmitLabel(Hash->Sym);
506
448
      for (const auto *Value : Hash->Values)
507
456
        emitEntry(*static_cast<const DataT *>(Value));
508
448
      Asm->OutStreamer->AddComment("End of list: " + Hash->Name.getString());
509
448
      Asm->emitInt32(0);
510
448
    }
511
313
  }
512
61
}
AccelTable.cpp:(anonymous namespace)::Dwarf5AccelTableWriter<llvm::DWARF5AccelTableStaticData>::emitData() const
Line
Count
Source
500
2
template <typename DataT> void Dwarf5AccelTableWriter<DataT>::emitData() const {
501
2
  Asm->OutStreamer->EmitLabel(EntryPool);
502
18
  for (auto &Bucket : Contents.getBuckets()) {
503
18
    for (auto *Hash : Bucket) {
504
18
      // Remember to emit the label for our offset.
505
18
      Asm->OutStreamer->EmitLabel(Hash->Sym);
506
18
      for (const auto *Value : Hash->Values)
507
24
        emitEntry(*static_cast<const DataT *>(Value));
508
18
      Asm->OutStreamer->AddComment("End of list: " + Hash->Name.getString());
509
18
      Asm->emitInt32(0);
510
18
    }
511
18
  }
512
2
}
513
514
template <typename DataT>
515
Dwarf5AccelTableWriter<DataT>::Dwarf5AccelTableWriter(
516
    AsmPrinter *Asm, const AccelTableBase &Contents,
517
    ArrayRef<MCSymbol *> CompUnits,
518
    llvm::function_ref<unsigned(const DataT &)> getCUIndexForEntry)
519
    : AccelTableWriter(Asm, Contents, false),
520
      Header(CompUnits.size(), Contents.getBucketCount(),
521
             Contents.getUniqueNameCount()),
522
63
      CompUnits(CompUnits), getCUIndexForEntry(std::move(getCUIndexForEntry)) {
523
63
  DenseSet<uint32_t> UniqueTags = getUniqueTags();
524
63
  SmallVector<AttributeEncoding, 2> UniformAttributes = getUniformAttributes();
525
63
526
63
  Abbreviations.reserve(UniqueTags.size());
527
63
  for (uint32_t Tag : UniqueTags)
528
134
    Abbreviations.try_emplace(Tag, UniformAttributes);
529
63
}
AccelTable.cpp:(anonymous namespace)::Dwarf5AccelTableWriter<llvm::DWARF5AccelTableData>::Dwarf5AccelTableWriter(llvm::AsmPrinter*, llvm::AccelTableBase const&, llvm::ArrayRef<llvm::MCSymbol*>, llvm::function_ref<unsigned int (llvm::DWARF5AccelTableData const&)>)
Line
Count
Source
522
61
      CompUnits(CompUnits), getCUIndexForEntry(std::move(getCUIndexForEntry)) {
523
61
  DenseSet<uint32_t> UniqueTags = getUniqueTags();
524
61
  SmallVector<AttributeEncoding, 2> UniformAttributes = getUniformAttributes();
525
61
526
61
  Abbreviations.reserve(UniqueTags.size());
527
61
  for (uint32_t Tag : UniqueTags)
528
128
    Abbreviations.try_emplace(Tag, UniformAttributes);
529
61
}
AccelTable.cpp:(anonymous namespace)::Dwarf5AccelTableWriter<llvm::DWARF5AccelTableStaticData>::Dwarf5AccelTableWriter(llvm::AsmPrinter*, llvm::AccelTableBase const&, llvm::ArrayRef<llvm::MCSymbol*>, llvm::function_ref<unsigned int (llvm::DWARF5AccelTableStaticData const&)>)
Line
Count
Source
522
2
      CompUnits(CompUnits), getCUIndexForEntry(std::move(getCUIndexForEntry)) {
523
2
  DenseSet<uint32_t> UniqueTags = getUniqueTags();
524
2
  SmallVector<AttributeEncoding, 2> UniformAttributes = getUniformAttributes();
525
2
526
2
  Abbreviations.reserve(UniqueTags.size());
527
2
  for (uint32_t Tag : UniqueTags)
528
6
    Abbreviations.try_emplace(Tag, UniformAttributes);
529
2
}
530
531
63
template <typename DataT> void Dwarf5AccelTableWriter<DataT>::emit() const {
532
63
  Header.emit(*this);
533
63
  emitCUList();
534
63
  emitBuckets();
535
63
  emitHashes();
536
63
  emitStringOffsets();
537
63
  emitOffsets(EntryPool);
538
63
  emitAbbrevs();
539
63
  emitData();
540
63
  Asm->OutStreamer->EmitValueToAlignment(4, 0);
541
63
  Asm->OutStreamer->EmitLabel(ContributionEnd);
542
63
}
AccelTable.cpp:(anonymous namespace)::Dwarf5AccelTableWriter<llvm::DWARF5AccelTableData>::emit() const
Line
Count
Source
531
61
template <typename DataT> void Dwarf5AccelTableWriter<DataT>::emit() const {
532
61
  Header.emit(*this);
533
61
  emitCUList();
534
61
  emitBuckets();
535
61
  emitHashes();
536
61
  emitStringOffsets();
537
61
  emitOffsets(EntryPool);
538
61
  emitAbbrevs();
539
61
  emitData();
540
61
  Asm->OutStreamer->EmitValueToAlignment(4, 0);
541
61
  Asm->OutStreamer->EmitLabel(ContributionEnd);
542
61
}
AccelTable.cpp:(anonymous namespace)::Dwarf5AccelTableWriter<llvm::DWARF5AccelTableStaticData>::emit() const
Line
Count
Source
531
2
template <typename DataT> void Dwarf5AccelTableWriter<DataT>::emit() const {
532
2
  Header.emit(*this);
533
2
  emitCUList();
534
2
  emitBuckets();
535
2
  emitHashes();
536
2
  emitStringOffsets();
537
2
  emitOffsets(EntryPool);
538
2
  emitAbbrevs();
539
2
  emitData();
540
2
  Asm->OutStreamer->EmitValueToAlignment(4, 0);
541
2
  Asm->OutStreamer->EmitLabel(ContributionEnd);
542
2
}
543
544
void llvm::emitAppleAccelTableImpl(AsmPrinter *Asm, AccelTableBase &Contents,
545
                                   StringRef Prefix, const MCSymbol *SecBegin,
546
10.6k
                                   ArrayRef<AppleAccelTableData::Atom> Atoms) {
547
10.6k
  Contents.finalize(Asm, Prefix);
548
10.6k
  AppleAccelTableWriter(Asm, Contents, Atoms, SecBegin).emit();
549
10.6k
}
550
551
void llvm::emitDWARF5AccelTable(
552
    AsmPrinter *Asm, AccelTable<DWARF5AccelTableData> &Contents,
553
204
    const DwarfDebug &DD, ArrayRef<std::unique_ptr<DwarfCompileUnit>> CUs) {
554
204
  std::vector<MCSymbol *> CompUnits;
555
204
  SmallVector<unsigned, 1> CUIndex(CUs.size());
556
204
  int Count = 0;
557
469
  for (const auto &CU : enumerate(CUs)) {
558
469
    if (CU.value()->getCUNode()->getNameTableKind() !=
559
469
        DICompileUnit::DebugNameTableKind::Default)
560
146
      continue;
561
323
    CUIndex[CU.index()] = Count++;
562
323
    assert(CU.index() == CU.value()->getUniqueID());
563
323
    const DwarfCompileUnit *MainCU =
564
323
        DD.useSplitDwarf() ? 
CU.value()->getSkeleton()10
:
CU.value().get()313
;
565
323
    CompUnits.push_back(MainCU->getLabelBegin());
566
323
  }
567
204
568
204
  if (CompUnits.empty())
569
143
    return;
570
61
571
61
  Asm->OutStreamer->SwitchSection(
572
61
      Asm->getObjFileLowering().getDwarfDebugNamesSection());
573
61
574
61
  Contents.finalize(Asm, "names");
575
61
  Dwarf5AccelTableWriter<DWARF5AccelTableData>(
576
61
      Asm, Contents, CompUnits,
577
275
      [&](const DWARF5AccelTableData &Entry) {
578
275
        const DIE *CUDie = Entry.getDie().getUnitDie();
579
275
        return CUIndex[DD.lookupCU(CUDie)->getUniqueID()];
580
275
      })
581
61
      .emit();
582
61
}
583
584
void llvm::emitDWARF5AccelTable(
585
    AsmPrinter *Asm, AccelTable<DWARF5AccelTableStaticData> &Contents,
586
    ArrayRef<MCSymbol *> CUs,
587
    llvm::function_ref<unsigned(const DWARF5AccelTableStaticData &)>
588
2
        getCUIndexForEntry) {
589
2
  Contents.finalize(Asm, "names");
590
2
  Dwarf5AccelTableWriter<DWARF5AccelTableStaticData>(Asm, Contents, CUs,
591
2
                                                     getCUIndexForEntry)
592
2
      .emit();
593
2
}
594
595
314k
void AppleAccelTableOffsetData::emit(AsmPrinter *Asm) const {
596
314k
  Asm->emitInt32(Die.getDebugSectionOffset());
597
314k
}
598
599
820
void AppleAccelTableTypeData::emit(AsmPrinter *Asm) const {
600
820
  Asm->emitInt32(Die.getDebugSectionOffset());
601
820
  Asm->emitInt16(Die.getTag());
602
820
  Asm->emitInt8(0);
603
820
}
604
605
515
void AppleAccelTableStaticOffsetData::emit(AsmPrinter *Asm) const {
606
515
  Asm->emitInt32(Offset);
607
515
}
608
609
304
void AppleAccelTableStaticTypeData::emit(AsmPrinter *Asm) const {
610
304
  Asm->emitInt32(Offset);
611
304
  Asm->emitInt16(Tag);
612
304
  Asm->emitInt8(ObjCClassIsImplementation ? 
dwarf::DW_FLAG_type_implementation3
613
304
                                          : 
0301
);
614
304
  Asm->emitInt32(QualifiedNameHash);
615
304
}
616
617
constexpr AppleAccelTableData::Atom AppleAccelTableTypeData::Atoms[];
618
constexpr AppleAccelTableData::Atom AppleAccelTableOffsetData::Atoms[];
619
constexpr AppleAccelTableData::Atom AppleAccelTableStaticOffsetData::Atoms[];
620
constexpr AppleAccelTableData::Atom AppleAccelTableStaticTypeData::Atoms[];
621
622
#ifndef NDEBUG
623
void AppleAccelTableWriter::Header::print(raw_ostream &OS) const {
624
  OS << "Magic: " << format("0x%x", Magic) << "\n"
625
     << "Version: " << Version << "\n"
626
     << "Hash Function: " << HashFunction << "\n"
627
     << "Bucket Count: " << BucketCount << "\n"
628
     << "Header Data Length: " << HeaderDataLength << "\n";
629
}
630
631
void AppleAccelTableData::Atom::print(raw_ostream &OS) const {
632
  OS << "Type: " << dwarf::AtomTypeString(Type) << "\n"
633
     << "Form: " << dwarf::FormEncodingString(Form) << "\n";
634
}
635
636
void AppleAccelTableWriter::HeaderData::print(raw_ostream &OS) const {
637
  OS << "DIE Offset Base: " << DieOffsetBase << "\n";
638
  for (auto Atom : Atoms)
639
    Atom.print(OS);
640
}
641
642
void AppleAccelTableWriter::print(raw_ostream &OS) const {
643
  Header.print(OS);
644
  HeaderData.print(OS);
645
  Contents.print(OS);
646
  SecBegin->print(OS, nullptr);
647
}
648
649
void AccelTableBase::HashData::print(raw_ostream &OS) const {
650
  OS << "Name: " << Name.getString() << "\n";
651
  OS << "  Hash Value: " << format("0x%x", HashValue) << "\n";
652
  OS << "  Symbol: ";
653
  if (Sym)
654
    OS << *Sym;
655
  else
656
    OS << "<none>";
657
  OS << "\n";
658
  for (auto *Value : Values)
659
    Value->print(OS);
660
}
661
662
void AccelTableBase::print(raw_ostream &OS) const {
663
  // Print Content.
664
  OS << "Entries: \n";
665
  for (const auto &Entry : Entries) {
666
    OS << "Name: " << Entry.first() << "\n";
667
    for (auto *V : Entry.second.Values)
668
      V->print(OS);
669
  }
670
671
  OS << "Buckets and Hashes: \n";
672
  for (auto &Bucket : Buckets)
673
    for (auto &Hash : Bucket)
674
      Hash->print(OS);
675
676
  OS << "Data: \n";
677
  for (auto &E : Entries)
678
    E.second.print(OS);
679
}
680
681
void DWARF5AccelTableData::print(raw_ostream &OS) const {
682
  OS << "  Offset: " << getDieOffset() << "\n";
683
  OS << "  Tag: " << dwarf::TagString(getDieTag()) << "\n";
684
}
685
686
void DWARF5AccelTableStaticData::print(raw_ostream &OS) const {
687
  OS << "  Offset: " << getDieOffset() << "\n";
688
  OS << "  Tag: " << dwarf::TagString(getDieTag()) << "\n";
689
}
690
691
void AppleAccelTableOffsetData::print(raw_ostream &OS) const {
692
  OS << "  Offset: " << Die.getOffset() << "\n";
693
}
694
695
void AppleAccelTableTypeData::print(raw_ostream &OS) const {
696
  OS << "  Offset: " << Die.getOffset() << "\n";
697
  OS << "  Tag: " << dwarf::TagString(Die.getTag()) << "\n";
698
}
699
700
void AppleAccelTableStaticOffsetData::print(raw_ostream &OS) const {
701
  OS << "  Static Offset: " << Offset << "\n";
702
}
703
704
void AppleAccelTableStaticTypeData::print(raw_ostream &OS) const {
705
  OS << "  Static Offset: " << Offset << "\n";
706
  OS << "  QualifiedNameHash: " << format("%x\n", QualifiedNameHash) << "\n";
707
  OS << "  Tag: " << dwarf::TagString(Tag) << "\n";
708
  OS << "  ObjCClassIsImplementation: "
709
     << (ObjCClassIsImplementation ? "true" : "false");
710
  OS << "\n";
711
}
712
#endif