2018-01-29 14:52:41 +00:00
|
|
|
//===- llvm/CodeGen/AsmPrinter/AccelTable.cpp - Accelerator Tables --------===//
|
2011-11-07 09:18:42 +00:00
|
|
|
//
|
2019-01-19 08:50:56 +00:00
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
2011-11-07 09:18:42 +00:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
2018-01-29 14:52:41 +00:00
|
|
|
// This file contains support for writing accelerator tables.
|
2011-11-07 09:18:42 +00:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2018-01-29 14:52:41 +00:00
|
|
|
#include "llvm/CodeGen/AccelTable.h"
|
2018-04-04 14:42:14 +00:00
|
|
|
#include "DwarfCompileUnit.h"
|
2023-11-18 06:36:33 -08:00
|
|
|
#include "DwarfUnit.h"
|
[AsmPrinter][DebugNames] Implement DW_IDX_parent entries (#77457)
This implements the ideas discussed in [1].
To summarize, this commit changes AsmPrinter so that it outputs
DW_IDX_parent information for debug_name entries. It will enable
debuggers to speed up queries for fully qualified types (based on a
DWARFDeclContext) significantly, as debuggers will no longer need to
parse the entire CU in order to inspect the parent chain of a DIE.
Instead, a debugger can simply take the parent DIE offset from the
accelerator table and peek at its name in the debug_info/debug_str
sections.
The implementation uses two types of DW_FORM for the DW_IDX_parent
attribute:
1. DW_FORM_ref4, which points to the accelerator table entry for the
parent.
2. DW_FORM_flag_present, when the entry has a parent that is not in the
table (that is, the parent doesn't have a name, or isn't allowed to be
in the table as per the DWARF spec). This is space-efficient, since it
takes 0 bytes.
The implementation works by:
1. Changing how abbreviations are encoded (so that they encode which
form, if
any, was used to encode IDX_Parent)
2. Creating an MCLabel per accelerator table entry, so that they may be
referred by IDX_parent references.
When all patches related to this are merged, we are able to show that
evaluating an expression such as:
```
lldb --batch -o 'b CodeGenFunction::GenerateCode' -o run -o 'expr Fn' -- \
clang++ -c -g test.cpp -o /dev/null
```
is far faster: from ~5000 ms to ~1500ms.
Building llvm-project + clang with and without this patch, and looking
at its impact on object file size:
```
ls -la $(find build_stage2_Debug_idx_parent_assert_dwarf5 -name \*.cpp.o) | awk '{s+=$5} END {printf "%\047d\n", s}'
11,507,327,592
-la $(find build_stage2_Debug_no_idx_parent_assert_dwarf5 -name \*.cpp.o) | awk '{s+=$5} END {printf "%\047d\n", s}'
11,436,446,616
```
That is, an increase of 0.62% in total object file size.
Looking only at debug_names:
```
$stage1_build/bin/llvm-objdump --section-headers $(find build_stage2_Debug_idx_parent_assert_dwarf5 -name \*.cpp.o) | grep __debug_names | awk '{s+="0x"$3} END {printf "%\047d\n", s}'
440,772,348
$stage1_build/bin/llvm-objdump --section-headers $(find build_stage2_Debug_no_idx_parent_assert_dwarf5 -name \*.cpp.o) | grep __debug_names | awk '{s+="0x"$3} END {printf "%\047d\n", s}'
369,867,920
```
That is an increase of 19%.
DWARF Linkers need to be changed in order to support this. This commit
already brings support to "base" linker, but it does not attempt to
modify the parallel linker. Accelerator entries refer to the
corresponding DIE offset, and this patch also requires the parent DIE
offset -- it's not clear how the parallel linker can access this. It may
be obvious to someone familiar with it, but it would be nice to get help
from its authors.
[1]:
https://discourse.llvm.org/t/rfc-improve-dwarf-5-debug-names-type-lookup-parsing-speed/74151/
2024-01-19 09:19:09 -08:00
|
|
|
#include "llvm/ADT/DenseSet.h"
|
2012-03-26 14:17:26 +00:00
|
|
|
#include "llvm/ADT/STLExtras.h"
|
2012-12-03 16:50:05 +00:00
|
|
|
#include "llvm/ADT/Twine.h"
|
2017-08-17 21:26:39 +00:00
|
|
|
#include "llvm/BinaryFormat/Dwarf.h"
|
2011-11-07 09:18:42 +00:00
|
|
|
#include "llvm/CodeGen/AsmPrinter.h"
|
2015-01-05 21:29:41 +00:00
|
|
|
#include "llvm/CodeGen/DIE.h"
|
2011-11-07 09:18:42 +00:00
|
|
|
#include "llvm/MC/MCStreamer.h"
|
2018-07-16 10:52:27 +00:00
|
|
|
#include "llvm/MC/MCSymbol.h"
|
2017-08-17 21:26:39 +00:00
|
|
|
#include "llvm/Support/raw_ostream.h"
|
2018-08-16 21:29:55 +00:00
|
|
|
#include "llvm/Target/TargetLoweringObjectFile.h"
|
2017-08-17 21:26:39 +00:00
|
|
|
#include <algorithm>
|
|
|
|
#include <cstddef>
|
|
|
|
#include <cstdint>
|
|
|
|
#include <limits>
|
|
|
|
#include <vector>
|
2011-11-07 09:18:42 +00:00
|
|
|
|
|
|
|
using namespace llvm;
|
|
|
|
|
[CodeGen] Refactor AppleAccelTable
Summary:
This commit separates the abstract accelerator table data structure
from the code for writing out an on-disk representation of a specific
accelerator table format. The idea is that former (now called
AccelTable<T>) can be reused for the DWARF v5 accelerator tables
as-is, without any further customizations.
Some bits of the emission code (now living in the EmissionContext class)
can be reused for DWARF v5 as well, but the subtle differences in the
layout of various subtables mean the sharing is not always possible.
(Also, the individual emit*** functions are fairly simple so there's a
tradeoff between making a bigger general-purpose function, and two
smaller targeted functions.)
Another advantage of this setup is that more of the serialization logic
can be hidden in the .cpp file -- I have moved declarations of the
header and all the emission functions there.
Reviewers: JDevlieghere, aprantl, probinson, dblaikie
Subscribers: echristo, clayborg, vleschuk, llvm-commits
Differential Revision: https://reviews.llvm.org/D43285
llvm-svn: 325516
2018-02-19 16:12:20 +00:00
|
|
|
void AccelTableBase::computeBucketCount() {
|
2024-02-21 08:26:05 -08:00
|
|
|
SmallVector<uint32_t, 0> Uniques;
|
[CodeGen] Refactor AppleAccelTable
Summary:
This commit separates the abstract accelerator table data structure
from the code for writing out an on-disk representation of a specific
accelerator table format. The idea is that former (now called
AccelTable<T>) can be reused for the DWARF v5 accelerator tables
as-is, without any further customizations.
Some bits of the emission code (now living in the EmissionContext class)
can be reused for DWARF v5 as well, but the subtle differences in the
layout of various subtables mean the sharing is not always possible.
(Also, the individual emit*** functions are fairly simple so there's a
tradeoff between making a bigger general-purpose function, and two
smaller targeted functions.)
Another advantage of this setup is that more of the serialization logic
can be hidden in the .cpp file -- I have moved declarations of the
header and all the emission functions there.
Reviewers: JDevlieghere, aprantl, probinson, dblaikie
Subscribers: echristo, clayborg, vleschuk, llvm-commits
Differential Revision: https://reviews.llvm.org/D43285
llvm-svn: 325516
2018-02-19 16:12:20 +00:00
|
|
|
Uniques.reserve(Entries.size());
|
|
|
|
for (const auto &E : Entries)
|
|
|
|
Uniques.push_back(E.second.HashValue);
|
2024-04-09 11:02:39 -07:00
|
|
|
llvm::sort(Uniques);
|
|
|
|
UniqueHashCount = llvm::unique(Uniques) - Uniques.begin();
|
|
|
|
BucketCount = dwarf::getDebugNamesBucketCount(UniqueHashCount);
|
[CodeGen] Refactor AppleAccelTable
Summary:
This commit separates the abstract accelerator table data structure
from the code for writing out an on-disk representation of a specific
accelerator table format. The idea is that former (now called
AccelTable<T>) can be reused for the DWARF v5 accelerator tables
as-is, without any further customizations.
Some bits of the emission code (now living in the EmissionContext class)
can be reused for DWARF v5 as well, but the subtle differences in the
layout of various subtables mean the sharing is not always possible.
(Also, the individual emit*** functions are fairly simple so there's a
tradeoff between making a bigger general-purpose function, and two
smaller targeted functions.)
Another advantage of this setup is that more of the serialization logic
can be hidden in the .cpp file -- I have moved declarations of the
header and all the emission functions there.
Reviewers: JDevlieghere, aprantl, probinson, dblaikie
Subscribers: echristo, clayborg, vleschuk, llvm-commits
Differential Revision: https://reviews.llvm.org/D43285
llvm-svn: 325516
2018-02-19 16:12:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void AccelTableBase::finalize(AsmPrinter *Asm, StringRef Prefix) {
|
|
|
|
// Create the individual hash data outputs.
|
|
|
|
for (auto &E : Entries) {
|
|
|
|
// Unique the entries.
|
2019-04-23 14:51:27 +00:00
|
|
|
llvm::stable_sort(E.second.Values,
|
|
|
|
[](const AccelTableData *A, const AccelTableData *B) {
|
|
|
|
return *A < *B;
|
|
|
|
});
|
[CodeGen] Refactor AppleAccelTable
Summary:
This commit separates the abstract accelerator table data structure
from the code for writing out an on-disk representation of a specific
accelerator table format. The idea is that former (now called
AccelTable<T>) can be reused for the DWARF v5 accelerator tables
as-is, without any further customizations.
Some bits of the emission code (now living in the EmissionContext class)
can be reused for DWARF v5 as well, but the subtle differences in the
layout of various subtables mean the sharing is not always possible.
(Also, the individual emit*** functions are fairly simple so there's a
tradeoff between making a bigger general-purpose function, and two
smaller targeted functions.)
Another advantage of this setup is that more of the serialization logic
can be hidden in the .cpp file -- I have moved declarations of the
header and all the emission functions there.
Reviewers: JDevlieghere, aprantl, probinson, dblaikie
Subscribers: echristo, clayborg, vleschuk, llvm-commits
Differential Revision: https://reviews.llvm.org/D43285
llvm-svn: 325516
2018-02-19 16:12:20 +00:00
|
|
|
E.second.Values.erase(
|
|
|
|
std::unique(E.second.Values.begin(), E.second.Values.end()),
|
|
|
|
E.second.Values.end());
|
|
|
|
}
|
|
|
|
|
|
|
|
// Figure out how many buckets we need, then compute the bucket contents and
|
|
|
|
// the final ordering. The hashes and offsets can be emitted by walking these
|
|
|
|
// data structures. We add temporary symbols to the data so they can be
|
|
|
|
// referenced when emitting the offsets.
|
|
|
|
computeBucketCount();
|
|
|
|
|
|
|
|
// Compute bucket contents and final ordering.
|
|
|
|
Buckets.resize(BucketCount);
|
|
|
|
for (auto &E : Entries) {
|
|
|
|
uint32_t Bucket = E.second.HashValue % BucketCount;
|
|
|
|
Buckets[Bucket].push_back(&E.second);
|
|
|
|
E.second.Sym = Asm->createTempSymbol(Prefix);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Sort the contents of the buckets by hash value so that hash collisions end
|
|
|
|
// up together. Stable sort makes testing easier and doesn't cost much more.
|
|
|
|
for (auto &Bucket : Buckets)
|
2019-04-23 14:51:27 +00:00
|
|
|
llvm::stable_sort(Bucket, [](HashData *LHS, HashData *RHS) {
|
|
|
|
return LHS->HashValue < RHS->HashValue;
|
|
|
|
});
|
[CodeGen] Refactor AppleAccelTable
Summary:
This commit separates the abstract accelerator table data structure
from the code for writing out an on-disk representation of a specific
accelerator table format. The idea is that former (now called
AccelTable<T>) can be reused for the DWARF v5 accelerator tables
as-is, without any further customizations.
Some bits of the emission code (now living in the EmissionContext class)
can be reused for DWARF v5 as well, but the subtle differences in the
layout of various subtables mean the sharing is not always possible.
(Also, the individual emit*** functions are fairly simple so there's a
tradeoff between making a bigger general-purpose function, and two
smaller targeted functions.)
Another advantage of this setup is that more of the serialization logic
can be hidden in the .cpp file -- I have moved declarations of the
header and all the emission functions there.
Reviewers: JDevlieghere, aprantl, probinson, dblaikie
Subscribers: echristo, clayborg, vleschuk, llvm-commits
Differential Revision: https://reviews.llvm.org/D43285
llvm-svn: 325516
2018-02-19 16:12:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
namespace {
|
2018-04-04 14:42:14 +00:00
|
|
|
/// Base class for writing out Accelerator tables. It holds the common
|
|
|
|
/// functionality for the two Accelerator table types.
|
2018-07-09 08:47:38 +00:00
|
|
|
class AccelTableWriter {
|
[CodeGen] Refactor AppleAccelTable
Summary:
This commit separates the abstract accelerator table data structure
from the code for writing out an on-disk representation of a specific
accelerator table format. The idea is that former (now called
AccelTable<T>) can be reused for the DWARF v5 accelerator tables
as-is, without any further customizations.
Some bits of the emission code (now living in the EmissionContext class)
can be reused for DWARF v5 as well, but the subtle differences in the
layout of various subtables mean the sharing is not always possible.
(Also, the individual emit*** functions are fairly simple so there's a
tradeoff between making a bigger general-purpose function, and two
smaller targeted functions.)
Another advantage of this setup is that more of the serialization logic
can be hidden in the .cpp file -- I have moved declarations of the
header and all the emission functions there.
Reviewers: JDevlieghere, aprantl, probinson, dblaikie
Subscribers: echristo, clayborg, vleschuk, llvm-commits
Differential Revision: https://reviews.llvm.org/D43285
llvm-svn: 325516
2018-02-19 16:12:20 +00:00
|
|
|
protected:
|
|
|
|
AsmPrinter *const Asm; ///< Destination.
|
|
|
|
const AccelTableBase &Contents; ///< Data to emit.
|
|
|
|
|
|
|
|
/// Controls whether to emit duplicate hash and offset table entries for names
|
|
|
|
/// with identical hashes. Apple tables don't emit duplicate entries, DWARF v5
|
|
|
|
/// tables do.
|
|
|
|
const bool SkipIdenticalHashes;
|
|
|
|
|
|
|
|
void emitHashes() const;
|
|
|
|
|
|
|
|
/// Emit offsets to lists of entries with identical names. The offsets are
|
|
|
|
/// relative to the Base argument.
|
|
|
|
void emitOffsets(const MCSymbol *Base) const;
|
|
|
|
|
|
|
|
public:
|
2018-07-09 08:47:38 +00:00
|
|
|
AccelTableWriter(AsmPrinter *Asm, const AccelTableBase &Contents,
|
|
|
|
bool SkipIdenticalHashes)
|
[CodeGen] Refactor AppleAccelTable
Summary:
This commit separates the abstract accelerator table data structure
from the code for writing out an on-disk representation of a specific
accelerator table format. The idea is that former (now called
AccelTable<T>) can be reused for the DWARF v5 accelerator tables
as-is, without any further customizations.
Some bits of the emission code (now living in the EmissionContext class)
can be reused for DWARF v5 as well, but the subtle differences in the
layout of various subtables mean the sharing is not always possible.
(Also, the individual emit*** functions are fairly simple so there's a
tradeoff between making a bigger general-purpose function, and two
smaller targeted functions.)
Another advantage of this setup is that more of the serialization logic
can be hidden in the .cpp file -- I have moved declarations of the
header and all the emission functions there.
Reviewers: JDevlieghere, aprantl, probinson, dblaikie
Subscribers: echristo, clayborg, vleschuk, llvm-commits
Differential Revision: https://reviews.llvm.org/D43285
llvm-svn: 325516
2018-02-19 16:12:20 +00:00
|
|
|
: Asm(Asm), Contents(Contents), SkipIdenticalHashes(SkipIdenticalHashes) {
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2018-07-09 08:47:38 +00:00
|
|
|
class AppleAccelTableWriter : public AccelTableWriter {
|
[CodeGen] Refactor AppleAccelTable
Summary:
This commit separates the abstract accelerator table data structure
from the code for writing out an on-disk representation of a specific
accelerator table format. The idea is that former (now called
AccelTable<T>) can be reused for the DWARF v5 accelerator tables
as-is, without any further customizations.
Some bits of the emission code (now living in the EmissionContext class)
can be reused for DWARF v5 as well, but the subtle differences in the
layout of various subtables mean the sharing is not always possible.
(Also, the individual emit*** functions are fairly simple so there's a
tradeoff between making a bigger general-purpose function, and two
smaller targeted functions.)
Another advantage of this setup is that more of the serialization logic
can be hidden in the .cpp file -- I have moved declarations of the
header and all the emission functions there.
Reviewers: JDevlieghere, aprantl, probinson, dblaikie
Subscribers: echristo, clayborg, vleschuk, llvm-commits
Differential Revision: https://reviews.llvm.org/D43285
llvm-svn: 325516
2018-02-19 16:12:20 +00:00
|
|
|
using Atom = AppleAccelTableData::Atom;
|
|
|
|
|
|
|
|
/// The fixed header of an Apple Accelerator Table.
|
|
|
|
struct Header {
|
|
|
|
uint32_t Magic = MagicHash;
|
|
|
|
uint16_t Version = 1;
|
|
|
|
uint16_t HashFunction = dwarf::DW_hash_function_djb;
|
|
|
|
uint32_t BucketCount;
|
|
|
|
uint32_t HashCount;
|
|
|
|
uint32_t HeaderDataLength;
|
|
|
|
|
|
|
|
/// 'HASH' magic value to detect endianness.
|
|
|
|
static const uint32_t MagicHash = 0x48415348;
|
|
|
|
|
|
|
|
Header(uint32_t BucketCount, uint32_t UniqueHashCount, uint32_t DataLength)
|
|
|
|
: BucketCount(BucketCount), HashCount(UniqueHashCount),
|
|
|
|
HeaderDataLength(DataLength) {}
|
|
|
|
|
|
|
|
void emit(AsmPrinter *Asm) const;
|
|
|
|
#ifndef NDEBUG
|
|
|
|
void print(raw_ostream &OS) const;
|
|
|
|
void dump() const { print(dbgs()); }
|
|
|
|
#endif
|
|
|
|
};
|
|
|
|
|
|
|
|
/// The HeaderData describes the structure of an Apple accelerator table
|
|
|
|
/// through a list of Atoms.
|
|
|
|
struct HeaderData {
|
|
|
|
/// In the case of data that is referenced via DW_FORM_ref_* the offset
|
|
|
|
/// base is used to describe the offset for all forms in the list of atoms.
|
|
|
|
uint32_t DieOffsetBase;
|
|
|
|
|
|
|
|
const SmallVector<Atom, 4> Atoms;
|
|
|
|
|
|
|
|
HeaderData(ArrayRef<Atom> AtomList, uint32_t Offset = 0)
|
|
|
|
: DieOffsetBase(Offset), Atoms(AtomList.begin(), AtomList.end()) {}
|
|
|
|
|
|
|
|
void emit(AsmPrinter *Asm) const;
|
|
|
|
#ifndef NDEBUG
|
|
|
|
void print(raw_ostream &OS) const;
|
|
|
|
void dump() const { print(dbgs()); }
|
|
|
|
#endif
|
|
|
|
};
|
|
|
|
|
|
|
|
Header Header;
|
|
|
|
HeaderData HeaderData;
|
|
|
|
const MCSymbol *SecBegin;
|
|
|
|
|
|
|
|
void emitBuckets() const;
|
|
|
|
void emitData() const;
|
|
|
|
|
|
|
|
public:
|
2018-07-09 08:47:38 +00:00
|
|
|
AppleAccelTableWriter(AsmPrinter *Asm, const AccelTableBase &Contents,
|
|
|
|
ArrayRef<Atom> Atoms, const MCSymbol *SecBegin)
|
|
|
|
: AccelTableWriter(Asm, Contents, true),
|
[CodeGen] Refactor AppleAccelTable
Summary:
This commit separates the abstract accelerator table data structure
from the code for writing out an on-disk representation of a specific
accelerator table format. The idea is that former (now called
AccelTable<T>) can be reused for the DWARF v5 accelerator tables
as-is, without any further customizations.
Some bits of the emission code (now living in the EmissionContext class)
can be reused for DWARF v5 as well, but the subtle differences in the
layout of various subtables mean the sharing is not always possible.
(Also, the individual emit*** functions are fairly simple so there's a
tradeoff between making a bigger general-purpose function, and two
smaller targeted functions.)
Another advantage of this setup is that more of the serialization logic
can be hidden in the .cpp file -- I have moved declarations of the
header and all the emission functions there.
Reviewers: JDevlieghere, aprantl, probinson, dblaikie
Subscribers: echristo, clayborg, vleschuk, llvm-commits
Differential Revision: https://reviews.llvm.org/D43285
llvm-svn: 325516
2018-02-19 16:12:20 +00:00
|
|
|
Header(Contents.getBucketCount(), Contents.getUniqueHashCount(),
|
|
|
|
8 + (Atoms.size() * 4)),
|
|
|
|
HeaderData(Atoms), SecBegin(SecBegin) {}
|
|
|
|
|
|
|
|
void emit() const;
|
|
|
|
|
|
|
|
#ifndef NDEBUG
|
|
|
|
void print(raw_ostream &OS) const;
|
|
|
|
void dump() const { print(dbgs()); }
|
|
|
|
#endif
|
|
|
|
};
|
2018-04-04 14:42:14 +00:00
|
|
|
|
2018-07-16 10:52:27 +00:00
|
|
|
/// Class responsible for emitting a DWARF v5 Accelerator Table. The only
|
|
|
|
/// public function is emit(), which performs the actual emission.
|
|
|
|
///
|
2024-01-05 11:01:19 -03:00
|
|
|
/// A callback abstracts the logic to provide a CU index for a given entry.
|
2018-07-09 08:47:38 +00:00
|
|
|
class Dwarf5AccelTableWriter : public AccelTableWriter {
|
2018-04-04 14:42:14 +00:00
|
|
|
struct Header {
|
|
|
|
uint16_t Version = 5;
|
|
|
|
uint16_t Padding = 0;
|
|
|
|
uint32_t CompUnitCount;
|
|
|
|
uint32_t LocalTypeUnitCount = 0;
|
|
|
|
uint32_t ForeignTypeUnitCount = 0;
|
2023-04-21 12:22:28 +08:00
|
|
|
uint32_t BucketCount = 0;
|
|
|
|
uint32_t NameCount = 0;
|
2018-04-04 14:42:14 +00:00
|
|
|
uint32_t AbbrevTableSize = 0;
|
|
|
|
uint32_t AugmentationStringSize = sizeof(AugmentationString);
|
|
|
|
char AugmentationString[8] = {'L', 'L', 'V', 'M', '0', '7', '0', '0'};
|
|
|
|
|
2023-11-18 06:36:33 -08:00
|
|
|
Header(uint32_t CompUnitCount, uint32_t LocalTypeUnitCount,
|
2023-12-04 13:56:21 -08:00
|
|
|
uint32_t ForeignTypeUnitCount, uint32_t BucketCount,
|
|
|
|
uint32_t NameCount)
|
2023-11-18 06:36:33 -08:00
|
|
|
: CompUnitCount(CompUnitCount), LocalTypeUnitCount(LocalTypeUnitCount),
|
2023-12-04 13:56:21 -08:00
|
|
|
ForeignTypeUnitCount(ForeignTypeUnitCount), BucketCount(BucketCount),
|
|
|
|
NameCount(NameCount) {}
|
2018-04-04 14:42:14 +00:00
|
|
|
|
2021-02-25 20:39:45 -05:00
|
|
|
void emit(Dwarf5AccelTableWriter &Ctx);
|
2018-04-04 14:42:14 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
Header Header;
|
2024-02-14 12:22:53 -08:00
|
|
|
/// FoldingSet that uniques the abbreviations.
|
|
|
|
FoldingSet<DebugNamesAbbrev> AbbreviationsSet;
|
|
|
|
/// Vector containing DebugNames abbreviations for iteration in order.
|
|
|
|
SmallVector<DebugNamesAbbrev *, 5> AbbreviationsVector;
|
|
|
|
/// The bump allocator to use when creating DIEAbbrev objects in the uniqued
|
|
|
|
/// storage container.
|
|
|
|
BumpPtrAllocator Alloc;
|
2023-07-04 13:24:50 +02:00
|
|
|
ArrayRef<std::variant<MCSymbol *, uint64_t>> CompUnits;
|
2023-11-18 06:36:33 -08:00
|
|
|
ArrayRef<std::variant<MCSymbol *, uint64_t>> TypeUnits;
|
|
|
|
llvm::function_ref<std::optional<DWARF5AccelTable::UnitIndexAndEncoding>(
|
2024-01-05 11:01:19 -03:00
|
|
|
const DWARF5AccelTableData &)>
|
2023-11-18 06:36:33 -08:00
|
|
|
getIndexForEntry;
|
2021-02-25 20:39:45 -05:00
|
|
|
MCSymbol *ContributionEnd = nullptr;
|
2018-04-04 14:42:14 +00:00
|
|
|
MCSymbol *AbbrevStart = Asm->createTempSymbol("names_abbrev_start");
|
|
|
|
MCSymbol *AbbrevEnd = Asm->createTempSymbol("names_abbrev_end");
|
|
|
|
MCSymbol *EntryPool = Asm->createTempSymbol("names_entries");
|
2023-12-04 13:56:21 -08:00
|
|
|
// Indicates if this module is built with Split Dwarf enabled.
|
|
|
|
bool IsSplitDwarf = false;
|
[AsmPrinter][DebugNames] Implement DW_IDX_parent entries (#77457)
This implements the ideas discussed in [1].
To summarize, this commit changes AsmPrinter so that it outputs
DW_IDX_parent information for debug_name entries. It will enable
debuggers to speed up queries for fully qualified types (based on a
DWARFDeclContext) significantly, as debuggers will no longer need to
parse the entire CU in order to inspect the parent chain of a DIE.
Instead, a debugger can simply take the parent DIE offset from the
accelerator table and peek at its name in the debug_info/debug_str
sections.
The implementation uses two types of DW_FORM for the DW_IDX_parent
attribute:
1. DW_FORM_ref4, which points to the accelerator table entry for the
parent.
2. DW_FORM_flag_present, when the entry has a parent that is not in the
table (that is, the parent doesn't have a name, or isn't allowed to be
in the table as per the DWARF spec). This is space-efficient, since it
takes 0 bytes.
The implementation works by:
1. Changing how abbreviations are encoded (so that they encode which
form, if
any, was used to encode IDX_Parent)
2. Creating an MCLabel per accelerator table entry, so that they may be
referred by IDX_parent references.
When all patches related to this are merged, we are able to show that
evaluating an expression such as:
```
lldb --batch -o 'b CodeGenFunction::GenerateCode' -o run -o 'expr Fn' -- \
clang++ -c -g test.cpp -o /dev/null
```
is far faster: from ~5000 ms to ~1500ms.
Building llvm-project + clang with and without this patch, and looking
at its impact on object file size:
```
ls -la $(find build_stage2_Debug_idx_parent_assert_dwarf5 -name \*.cpp.o) | awk '{s+=$5} END {printf "%\047d\n", s}'
11,507,327,592
-la $(find build_stage2_Debug_no_idx_parent_assert_dwarf5 -name \*.cpp.o) | awk '{s+=$5} END {printf "%\047d\n", s}'
11,436,446,616
```
That is, an increase of 0.62% in total object file size.
Looking only at debug_names:
```
$stage1_build/bin/llvm-objdump --section-headers $(find build_stage2_Debug_idx_parent_assert_dwarf5 -name \*.cpp.o) | grep __debug_names | awk '{s+="0x"$3} END {printf "%\047d\n", s}'
440,772,348
$stage1_build/bin/llvm-objdump --section-headers $(find build_stage2_Debug_no_idx_parent_assert_dwarf5 -name \*.cpp.o) | grep __debug_names | awk '{s+="0x"$3} END {printf "%\047d\n", s}'
369,867,920
```
That is an increase of 19%.
DWARF Linkers need to be changed in order to support this. This commit
already brings support to "base" linker, but it does not attempt to
modify the parallel linker. Accelerator entries refer to the
corresponding DIE offset, and this patch also requires the parent DIE
offset -- it's not clear how the parallel linker can access this. It may
be obvious to someone familiar with it, but it would be nice to get help
from its authors.
[1]:
https://discourse.llvm.org/t/rfc-improve-dwarf-5-debug-names-type-lookup-parsing-speed/74151/
2024-01-19 09:19:09 -08:00
|
|
|
/// Stores the DIE offsets which are indexed by this table.
|
|
|
|
DenseSet<OffsetAndUnitID> IndexedOffsets;
|
2018-04-04 14:42:14 +00:00
|
|
|
|
2023-11-18 06:36:33 -08:00
|
|
|
void populateAbbrevsMap();
|
2018-04-04 14:42:14 +00:00
|
|
|
|
|
|
|
void emitCUList() const;
|
2023-11-18 06:36:33 -08:00
|
|
|
void emitTUList() const;
|
2018-04-04 14:42:14 +00:00
|
|
|
void emitBuckets() const;
|
|
|
|
void emitStringOffsets() const;
|
|
|
|
void emitAbbrevs() const;
|
[AsmPrinter][DebugNames] Implement DW_IDX_parent entries (#77457)
This implements the ideas discussed in [1].
To summarize, this commit changes AsmPrinter so that it outputs
DW_IDX_parent information for debug_name entries. It will enable
debuggers to speed up queries for fully qualified types (based on a
DWARFDeclContext) significantly, as debuggers will no longer need to
parse the entire CU in order to inspect the parent chain of a DIE.
Instead, a debugger can simply take the parent DIE offset from the
accelerator table and peek at its name in the debug_info/debug_str
sections.
The implementation uses two types of DW_FORM for the DW_IDX_parent
attribute:
1. DW_FORM_ref4, which points to the accelerator table entry for the
parent.
2. DW_FORM_flag_present, when the entry has a parent that is not in the
table (that is, the parent doesn't have a name, or isn't allowed to be
in the table as per the DWARF spec). This is space-efficient, since it
takes 0 bytes.
The implementation works by:
1. Changing how abbreviations are encoded (so that they encode which
form, if
any, was used to encode IDX_Parent)
2. Creating an MCLabel per accelerator table entry, so that they may be
referred by IDX_parent references.
When all patches related to this are merged, we are able to show that
evaluating an expression such as:
```
lldb --batch -o 'b CodeGenFunction::GenerateCode' -o run -o 'expr Fn' -- \
clang++ -c -g test.cpp -o /dev/null
```
is far faster: from ~5000 ms to ~1500ms.
Building llvm-project + clang with and without this patch, and looking
at its impact on object file size:
```
ls -la $(find build_stage2_Debug_idx_parent_assert_dwarf5 -name \*.cpp.o) | awk '{s+=$5} END {printf "%\047d\n", s}'
11,507,327,592
-la $(find build_stage2_Debug_no_idx_parent_assert_dwarf5 -name \*.cpp.o) | awk '{s+=$5} END {printf "%\047d\n", s}'
11,436,446,616
```
That is, an increase of 0.62% in total object file size.
Looking only at debug_names:
```
$stage1_build/bin/llvm-objdump --section-headers $(find build_stage2_Debug_idx_parent_assert_dwarf5 -name \*.cpp.o) | grep __debug_names | awk '{s+="0x"$3} END {printf "%\047d\n", s}'
440,772,348
$stage1_build/bin/llvm-objdump --section-headers $(find build_stage2_Debug_no_idx_parent_assert_dwarf5 -name \*.cpp.o) | grep __debug_names | awk '{s+="0x"$3} END {printf "%\047d\n", s}'
369,867,920
```
That is an increase of 19%.
DWARF Linkers need to be changed in order to support this. This commit
already brings support to "base" linker, but it does not attempt to
modify the parallel linker. Accelerator entries refer to the
corresponding DIE offset, and this patch also requires the parent DIE
offset -- it's not clear how the parallel linker can access this. It may
be obvious to someone familiar with it, but it would be nice to get help
from its authors.
[1]:
https://discourse.llvm.org/t/rfc-improve-dwarf-5-debug-names-type-lookup-parsing-speed/74151/
2024-01-19 09:19:09 -08:00
|
|
|
void emitEntry(
|
|
|
|
const DWARF5AccelTableData &Entry,
|
|
|
|
const DenseMap<OffsetAndUnitID, MCSymbol *> &DIEOffsetToAccelEntryLabel,
|
2024-02-14 12:22:53 -08:00
|
|
|
DenseSet<MCSymbol *> &EmittedAccelEntrySymbols);
|
[AsmPrinter][DebugNames] Implement DW_IDX_parent entries (#77457)
This implements the ideas discussed in [1].
To summarize, this commit changes AsmPrinter so that it outputs
DW_IDX_parent information for debug_name entries. It will enable
debuggers to speed up queries for fully qualified types (based on a
DWARFDeclContext) significantly, as debuggers will no longer need to
parse the entire CU in order to inspect the parent chain of a DIE.
Instead, a debugger can simply take the parent DIE offset from the
accelerator table and peek at its name in the debug_info/debug_str
sections.
The implementation uses two types of DW_FORM for the DW_IDX_parent
attribute:
1. DW_FORM_ref4, which points to the accelerator table entry for the
parent.
2. DW_FORM_flag_present, when the entry has a parent that is not in the
table (that is, the parent doesn't have a name, or isn't allowed to be
in the table as per the DWARF spec). This is space-efficient, since it
takes 0 bytes.
The implementation works by:
1. Changing how abbreviations are encoded (so that they encode which
form, if
any, was used to encode IDX_Parent)
2. Creating an MCLabel per accelerator table entry, so that they may be
referred by IDX_parent references.
When all patches related to this are merged, we are able to show that
evaluating an expression such as:
```
lldb --batch -o 'b CodeGenFunction::GenerateCode' -o run -o 'expr Fn' -- \
clang++ -c -g test.cpp -o /dev/null
```
is far faster: from ~5000 ms to ~1500ms.
Building llvm-project + clang with and without this patch, and looking
at its impact on object file size:
```
ls -la $(find build_stage2_Debug_idx_parent_assert_dwarf5 -name \*.cpp.o) | awk '{s+=$5} END {printf "%\047d\n", s}'
11,507,327,592
-la $(find build_stage2_Debug_no_idx_parent_assert_dwarf5 -name \*.cpp.o) | awk '{s+=$5} END {printf "%\047d\n", s}'
11,436,446,616
```
That is, an increase of 0.62% in total object file size.
Looking only at debug_names:
```
$stage1_build/bin/llvm-objdump --section-headers $(find build_stage2_Debug_idx_parent_assert_dwarf5 -name \*.cpp.o) | grep __debug_names | awk '{s+="0x"$3} END {printf "%\047d\n", s}'
440,772,348
$stage1_build/bin/llvm-objdump --section-headers $(find build_stage2_Debug_no_idx_parent_assert_dwarf5 -name \*.cpp.o) | grep __debug_names | awk '{s+="0x"$3} END {printf "%\047d\n", s}'
369,867,920
```
That is an increase of 19%.
DWARF Linkers need to be changed in order to support this. This commit
already brings support to "base" linker, but it does not attempt to
modify the parallel linker. Accelerator entries refer to the
corresponding DIE offset, and this patch also requires the parent DIE
offset -- it's not clear how the parallel linker can access this. It may
be obvious to someone familiar with it, but it would be nice to get help
from its authors.
[1]:
https://discourse.llvm.org/t/rfc-improve-dwarf-5-debug-names-type-lookup-parsing-speed/74151/
2024-01-19 09:19:09 -08:00
|
|
|
void emitData();
|
2018-04-04 14:42:14 +00:00
|
|
|
|
|
|
|
public:
|
2018-07-16 10:52:27 +00:00
|
|
|
Dwarf5AccelTableWriter(
|
|
|
|
AsmPrinter *Asm, const AccelTableBase &Contents,
|
2023-07-04 13:24:50 +02:00
|
|
|
ArrayRef<std::variant<MCSymbol *, uint64_t>> CompUnits,
|
2023-11-18 06:36:33 -08:00
|
|
|
ArrayRef<std::variant<MCSymbol *, uint64_t>> TypeUnits,
|
2024-01-05 11:01:19 -03:00
|
|
|
llvm::function_ref<std::optional<DWARF5AccelTable::UnitIndexAndEncoding>(
|
|
|
|
const DWARF5AccelTableData &)>
|
2023-12-04 13:56:21 -08:00
|
|
|
getIndexForEntry,
|
|
|
|
bool IsSplitDwarf);
|
2024-02-15 09:45:32 -08:00
|
|
|
~Dwarf5AccelTableWriter() {
|
|
|
|
for (DebugNamesAbbrev *Abbrev : AbbreviationsVector)
|
|
|
|
Abbrev->~DebugNamesAbbrev();
|
|
|
|
}
|
2021-02-25 20:39:45 -05:00
|
|
|
void emit();
|
2018-04-04 14:42:14 +00:00
|
|
|
};
|
[CodeGen] Refactor AppleAccelTable
Summary:
This commit separates the abstract accelerator table data structure
from the code for writing out an on-disk representation of a specific
accelerator table format. The idea is that former (now called
AccelTable<T>) can be reused for the DWARF v5 accelerator tables
as-is, without any further customizations.
Some bits of the emission code (now living in the EmissionContext class)
can be reused for DWARF v5 as well, but the subtle differences in the
layout of various subtables mean the sharing is not always possible.
(Also, the individual emit*** functions are fairly simple so there's a
tradeoff between making a bigger general-purpose function, and two
smaller targeted functions.)
Another advantage of this setup is that more of the serialization logic
can be hidden in the .cpp file -- I have moved declarations of the
header and all the emission functions there.
Reviewers: JDevlieghere, aprantl, probinson, dblaikie
Subscribers: echristo, clayborg, vleschuk, llvm-commits
Differential Revision: https://reviews.llvm.org/D43285
llvm-svn: 325516
2018-02-19 16:12:20 +00:00
|
|
|
} // namespace
|
|
|
|
|
2018-07-09 08:47:38 +00:00
|
|
|
void AccelTableWriter::emitHashes() const {
|
[CodeGen] Refactor AppleAccelTable
Summary:
This commit separates the abstract accelerator table data structure
from the code for writing out an on-disk representation of a specific
accelerator table format. The idea is that former (now called
AccelTable<T>) can be reused for the DWARF v5 accelerator tables
as-is, without any further customizations.
Some bits of the emission code (now living in the EmissionContext class)
can be reused for DWARF v5 as well, but the subtle differences in the
layout of various subtables mean the sharing is not always possible.
(Also, the individual emit*** functions are fairly simple so there's a
tradeoff between making a bigger general-purpose function, and two
smaller targeted functions.)
Another advantage of this setup is that more of the serialization logic
can be hidden in the .cpp file -- I have moved declarations of the
header and all the emission functions there.
Reviewers: JDevlieghere, aprantl, probinson, dblaikie
Subscribers: echristo, clayborg, vleschuk, llvm-commits
Differential Revision: https://reviews.llvm.org/D43285
llvm-svn: 325516
2018-02-19 16:12:20 +00:00
|
|
|
uint64_t PrevHash = std::numeric_limits<uint64_t>::max();
|
|
|
|
unsigned BucketIdx = 0;
|
2022-07-17 01:33:28 -07:00
|
|
|
for (const auto &Bucket : Contents.getBuckets()) {
|
|
|
|
for (const auto &Hash : Bucket) {
|
[CodeGen] Refactor AppleAccelTable
Summary:
This commit separates the abstract accelerator table data structure
from the code for writing out an on-disk representation of a specific
accelerator table format. The idea is that former (now called
AccelTable<T>) can be reused for the DWARF v5 accelerator tables
as-is, without any further customizations.
Some bits of the emission code (now living in the EmissionContext class)
can be reused for DWARF v5 as well, but the subtle differences in the
layout of various subtables mean the sharing is not always possible.
(Also, the individual emit*** functions are fairly simple so there's a
tradeoff between making a bigger general-purpose function, and two
smaller targeted functions.)
Another advantage of this setup is that more of the serialization logic
can be hidden in the .cpp file -- I have moved declarations of the
header and all the emission functions there.
Reviewers: JDevlieghere, aprantl, probinson, dblaikie
Subscribers: echristo, clayborg, vleschuk, llvm-commits
Differential Revision: https://reviews.llvm.org/D43285
llvm-svn: 325516
2018-02-19 16:12:20 +00:00
|
|
|
uint32_t HashValue = Hash->HashValue;
|
|
|
|
if (SkipIdenticalHashes && PrevHash == HashValue)
|
|
|
|
continue;
|
|
|
|
Asm->OutStreamer->AddComment("Hash in Bucket " + Twine(BucketIdx));
|
2018-03-29 23:32:54 +00:00
|
|
|
Asm->emitInt32(HashValue);
|
[CodeGen] Refactor AppleAccelTable
Summary:
This commit separates the abstract accelerator table data structure
from the code for writing out an on-disk representation of a specific
accelerator table format. The idea is that former (now called
AccelTable<T>) can be reused for the DWARF v5 accelerator tables
as-is, without any further customizations.
Some bits of the emission code (now living in the EmissionContext class)
can be reused for DWARF v5 as well, but the subtle differences in the
layout of various subtables mean the sharing is not always possible.
(Also, the individual emit*** functions are fairly simple so there's a
tradeoff between making a bigger general-purpose function, and two
smaller targeted functions.)
Another advantage of this setup is that more of the serialization logic
can be hidden in the .cpp file -- I have moved declarations of the
header and all the emission functions there.
Reviewers: JDevlieghere, aprantl, probinson, dblaikie
Subscribers: echristo, clayborg, vleschuk, llvm-commits
Differential Revision: https://reviews.llvm.org/D43285
llvm-svn: 325516
2018-02-19 16:12:20 +00:00
|
|
|
PrevHash = HashValue;
|
|
|
|
}
|
|
|
|
BucketIdx++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-07-09 08:47:38 +00:00
|
|
|
void AccelTableWriter::emitOffsets(const MCSymbol *Base) const {
|
[CodeGen] Refactor AppleAccelTable
Summary:
This commit separates the abstract accelerator table data structure
from the code for writing out an on-disk representation of a specific
accelerator table format. The idea is that former (now called
AccelTable<T>) can be reused for the DWARF v5 accelerator tables
as-is, without any further customizations.
Some bits of the emission code (now living in the EmissionContext class)
can be reused for DWARF v5 as well, but the subtle differences in the
layout of various subtables mean the sharing is not always possible.
(Also, the individual emit*** functions are fairly simple so there's a
tradeoff between making a bigger general-purpose function, and two
smaller targeted functions.)
Another advantage of this setup is that more of the serialization logic
can be hidden in the .cpp file -- I have moved declarations of the
header and all the emission functions there.
Reviewers: JDevlieghere, aprantl, probinson, dblaikie
Subscribers: echristo, clayborg, vleschuk, llvm-commits
Differential Revision: https://reviews.llvm.org/D43285
llvm-svn: 325516
2018-02-19 16:12:20 +00:00
|
|
|
const auto &Buckets = Contents.getBuckets();
|
|
|
|
uint64_t PrevHash = std::numeric_limits<uint64_t>::max();
|
|
|
|
for (size_t i = 0, e = Buckets.size(); i < e; ++i) {
|
|
|
|
for (auto *Hash : Buckets[i]) {
|
|
|
|
uint32_t HashValue = Hash->HashValue;
|
|
|
|
if (SkipIdenticalHashes && PrevHash == HashValue)
|
|
|
|
continue;
|
|
|
|
PrevHash = HashValue;
|
|
|
|
Asm->OutStreamer->AddComment("Offset in Bucket " + Twine(i));
|
2020-09-15 11:31:49 +07:00
|
|
|
Asm->emitLabelDifference(Hash->Sym, Base, Asm->getDwarfOffsetByteSize());
|
[CodeGen] Refactor AppleAccelTable
Summary:
This commit separates the abstract accelerator table data structure
from the code for writing out an on-disk representation of a specific
accelerator table format. The idea is that former (now called
AccelTable<T>) can be reused for the DWARF v5 accelerator tables
as-is, without any further customizations.
Some bits of the emission code (now living in the EmissionContext class)
can be reused for DWARF v5 as well, but the subtle differences in the
layout of various subtables mean the sharing is not always possible.
(Also, the individual emit*** functions are fairly simple so there's a
tradeoff between making a bigger general-purpose function, and two
smaller targeted functions.)
Another advantage of this setup is that more of the serialization logic
can be hidden in the .cpp file -- I have moved declarations of the
header and all the emission functions there.
Reviewers: JDevlieghere, aprantl, probinson, dblaikie
Subscribers: echristo, clayborg, vleschuk, llvm-commits
Differential Revision: https://reviews.llvm.org/D43285
llvm-svn: 325516
2018-02-19 16:12:20 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-07-09 08:47:38 +00:00
|
|
|
void AppleAccelTableWriter::Header::emit(AsmPrinter *Asm) const {
|
2015-04-24 19:11:51 +00:00
|
|
|
Asm->OutStreamer->AddComment("Header Magic");
|
2018-03-29 23:32:54 +00:00
|
|
|
Asm->emitInt32(Magic);
|
2015-04-24 19:11:51 +00:00
|
|
|
Asm->OutStreamer->AddComment("Header Version");
|
2018-03-29 23:32:54 +00:00
|
|
|
Asm->emitInt16(Version);
|
2015-04-24 19:11:51 +00:00
|
|
|
Asm->OutStreamer->AddComment("Header Hash Function");
|
2018-03-29 23:32:54 +00:00
|
|
|
Asm->emitInt16(HashFunction);
|
2015-04-24 19:11:51 +00:00
|
|
|
Asm->OutStreamer->AddComment("Header Bucket Count");
|
2018-03-29 23:32:54 +00:00
|
|
|
Asm->emitInt32(BucketCount);
|
2015-04-24 19:11:51 +00:00
|
|
|
Asm->OutStreamer->AddComment("Header Hash Count");
|
2018-03-29 23:32:54 +00:00
|
|
|
Asm->emitInt32(HashCount);
|
2015-04-24 19:11:51 +00:00
|
|
|
Asm->OutStreamer->AddComment("Header Data Length");
|
2018-03-29 23:32:54 +00:00
|
|
|
Asm->emitInt32(HeaderDataLength);
|
[CodeGen] Refactor AppleAccelTable
Summary:
This commit separates the abstract accelerator table data structure
from the code for writing out an on-disk representation of a specific
accelerator table format. The idea is that former (now called
AccelTable<T>) can be reused for the DWARF v5 accelerator tables
as-is, without any further customizations.
Some bits of the emission code (now living in the EmissionContext class)
can be reused for DWARF v5 as well, but the subtle differences in the
layout of various subtables mean the sharing is not always possible.
(Also, the individual emit*** functions are fairly simple so there's a
tradeoff between making a bigger general-purpose function, and two
smaller targeted functions.)
Another advantage of this setup is that more of the serialization logic
can be hidden in the .cpp file -- I have moved declarations of the
header and all the emission functions there.
Reviewers: JDevlieghere, aprantl, probinson, dblaikie
Subscribers: echristo, clayborg, vleschuk, llvm-commits
Differential Revision: https://reviews.llvm.org/D43285
llvm-svn: 325516
2018-02-19 16:12:20 +00:00
|
|
|
}
|
2018-01-29 14:52:34 +00:00
|
|
|
|
2018-07-09 08:47:38 +00:00
|
|
|
void AppleAccelTableWriter::HeaderData::emit(AsmPrinter *Asm) const {
|
2015-04-24 19:11:51 +00:00
|
|
|
Asm->OutStreamer->AddComment("HeaderData Die Offset Base");
|
2018-03-29 23:32:54 +00:00
|
|
|
Asm->emitInt32(DieOffsetBase);
|
2015-04-24 19:11:51 +00:00
|
|
|
Asm->OutStreamer->AddComment("HeaderData Atom Count");
|
2018-03-29 23:32:54 +00:00
|
|
|
Asm->emitInt32(Atoms.size());
|
2018-01-29 14:52:34 +00:00
|
|
|
|
[CodeGen] Refactor AppleAccelTable
Summary:
This commit separates the abstract accelerator table data structure
from the code for writing out an on-disk representation of a specific
accelerator table format. The idea is that former (now called
AccelTable<T>) can be reused for the DWARF v5 accelerator tables
as-is, without any further customizations.
Some bits of the emission code (now living in the EmissionContext class)
can be reused for DWARF v5 as well, but the subtle differences in the
layout of various subtables mean the sharing is not always possible.
(Also, the individual emit*** functions are fairly simple so there's a
tradeoff between making a bigger general-purpose function, and two
smaller targeted functions.)
Another advantage of this setup is that more of the serialization logic
can be hidden in the .cpp file -- I have moved declarations of the
header and all the emission functions there.
Reviewers: JDevlieghere, aprantl, probinson, dblaikie
Subscribers: echristo, clayborg, vleschuk, llvm-commits
Differential Revision: https://reviews.llvm.org/D43285
llvm-svn: 325516
2018-02-19 16:12:20 +00:00
|
|
|
for (const Atom &A : Atoms) {
|
2018-01-29 14:52:34 +00:00
|
|
|
Asm->OutStreamer->AddComment(dwarf::AtomTypeString(A.Type));
|
2018-03-29 23:32:54 +00:00
|
|
|
Asm->emitInt16(A.Type);
|
2018-01-29 14:52:34 +00:00
|
|
|
Asm->OutStreamer->AddComment(dwarf::FormEncodingString(A.Form));
|
2018-03-29 23:32:54 +00:00
|
|
|
Asm->emitInt16(A.Form);
|
2011-11-07 09:18:42 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-07-09 08:47:38 +00:00
|
|
|
void AppleAccelTableWriter::emitBuckets() const {
|
[CodeGen] Refactor AppleAccelTable
Summary:
This commit separates the abstract accelerator table data structure
from the code for writing out an on-disk representation of a specific
accelerator table format. The idea is that former (now called
AccelTable<T>) can be reused for the DWARF v5 accelerator tables
as-is, without any further customizations.
Some bits of the emission code (now living in the EmissionContext class)
can be reused for DWARF v5 as well, but the subtle differences in the
layout of various subtables mean the sharing is not always possible.
(Also, the individual emit*** functions are fairly simple so there's a
tradeoff between making a bigger general-purpose function, and two
smaller targeted functions.)
Another advantage of this setup is that more of the serialization logic
can be hidden in the .cpp file -- I have moved declarations of the
header and all the emission functions there.
Reviewers: JDevlieghere, aprantl, probinson, dblaikie
Subscribers: echristo, clayborg, vleschuk, llvm-commits
Differential Revision: https://reviews.llvm.org/D43285
llvm-svn: 325516
2018-02-19 16:12:20 +00:00
|
|
|
const auto &Buckets = Contents.getBuckets();
|
2011-11-07 09:18:42 +00:00
|
|
|
unsigned index = 0;
|
2011-11-08 18:38:40 +00:00
|
|
|
for (size_t i = 0, e = Buckets.size(); i < e; ++i) {
|
2015-04-24 19:11:51 +00:00
|
|
|
Asm->OutStreamer->AddComment("Bucket " + Twine(i));
|
2017-08-17 21:26:39 +00:00
|
|
|
if (!Buckets[i].empty())
|
2018-03-29 23:32:54 +00:00
|
|
|
Asm->emitInt32(index);
|
2011-11-07 09:18:42 +00:00
|
|
|
else
|
2018-03-29 23:32:54 +00:00
|
|
|
Asm->emitInt32(std::numeric_limits<uint32_t>::max());
|
2018-01-29 14:52:34 +00:00
|
|
|
// Buckets point in the list of hashes, not to the data. Do not increment
|
|
|
|
// the index multiple times in case of hash collisions.
|
2017-08-17 21:26:39 +00:00
|
|
|
uint64_t PrevHash = std::numeric_limits<uint64_t>::max();
|
2015-03-10 00:46:31 +00:00
|
|
|
for (auto *HD : Buckets[i]) {
|
|
|
|
uint32_t HashValue = HD->HashValue;
|
|
|
|
if (PrevHash != HashValue)
|
|
|
|
++index;
|
|
|
|
PrevHash = HashValue;
|
|
|
|
}
|
2011-11-07 09:18:42 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-07-09 08:47:38 +00:00
|
|
|
void AppleAccelTableWriter::emitData() const {
|
[CodeGen] Refactor AppleAccelTable
Summary:
This commit separates the abstract accelerator table data structure
from the code for writing out an on-disk representation of a specific
accelerator table format. The idea is that former (now called
AccelTable<T>) can be reused for the DWARF v5 accelerator tables
as-is, without any further customizations.
Some bits of the emission code (now living in the EmissionContext class)
can be reused for DWARF v5 as well, but the subtle differences in the
layout of various subtables mean the sharing is not always possible.
(Also, the individual emit*** functions are fairly simple so there's a
tradeoff between making a bigger general-purpose function, and two
smaller targeted functions.)
Another advantage of this setup is that more of the serialization logic
can be hidden in the .cpp file -- I have moved declarations of the
header and all the emission functions there.
Reviewers: JDevlieghere, aprantl, probinson, dblaikie
Subscribers: echristo, clayborg, vleschuk, llvm-commits
Differential Revision: https://reviews.llvm.org/D43285
llvm-svn: 325516
2018-02-19 16:12:20 +00:00
|
|
|
const auto &Buckets = Contents.getBuckets();
|
2021-02-10 20:01:21 -08:00
|
|
|
for (const AccelTableBase::HashList &Bucket : Buckets) {
|
2017-08-17 21:26:39 +00:00
|
|
|
uint64_t PrevHash = std::numeric_limits<uint64_t>::max();
|
2022-07-17 01:33:28 -07:00
|
|
|
for (const auto &Hash : Bucket) {
|
2018-01-29 14:52:34 +00:00
|
|
|
// Terminate the previous entry if there is no hash collision with the
|
|
|
|
// current one.
|
2017-08-17 21:26:39 +00:00
|
|
|
if (PrevHash != std::numeric_limits<uint64_t>::max() &&
|
2018-01-29 14:52:34 +00:00
|
|
|
PrevHash != Hash->HashValue)
|
2018-03-29 23:32:54 +00:00
|
|
|
Asm->emitInt32(0);
|
2011-11-07 09:18:42 +00:00
|
|
|
// Remember to emit the label for our offset.
|
2020-02-14 19:21:58 -08:00
|
|
|
Asm->OutStreamer->emitLabel(Hash->Sym);
|
2018-02-09 10:06:56 +00:00
|
|
|
Asm->OutStreamer->AddComment(Hash->Name.getString());
|
|
|
|
Asm->emitDwarfStringOffset(Hash->Name);
|
2015-04-24 19:11:51 +00:00
|
|
|
Asm->OutStreamer->AddComment("Num DIEs");
|
2018-03-29 23:32:54 +00:00
|
|
|
Asm->emitInt32(Hash->Values.size());
|
2024-01-08 17:04:07 -03:00
|
|
|
for (const auto *V : Hash->getValues<const AppleAccelTableData *>())
|
|
|
|
V->emit(Asm);
|
2018-01-29 14:52:34 +00:00
|
|
|
PrevHash = Hash->HashValue;
|
2011-11-07 09:18:42 +00:00
|
|
|
}
|
2015-03-10 00:46:31 +00:00
|
|
|
// Emit the final end marker for the bucket.
|
2021-02-10 20:01:21 -08:00
|
|
|
if (!Bucket.empty())
|
2018-03-29 23:32:54 +00:00
|
|
|
Asm->emitInt32(0);
|
2011-11-07 09:18:42 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-07-09 08:47:38 +00:00
|
|
|
void AppleAccelTableWriter::emit() const {
|
[CodeGen] Refactor AppleAccelTable
Summary:
This commit separates the abstract accelerator table data structure
from the code for writing out an on-disk representation of a specific
accelerator table format. The idea is that former (now called
AccelTable<T>) can be reused for the DWARF v5 accelerator tables
as-is, without any further customizations.
Some bits of the emission code (now living in the EmissionContext class)
can be reused for DWARF v5 as well, but the subtle differences in the
layout of various subtables mean the sharing is not always possible.
(Also, the individual emit*** functions are fairly simple so there's a
tradeoff between making a bigger general-purpose function, and two
smaller targeted functions.)
Another advantage of this setup is that more of the serialization logic
can be hidden in the .cpp file -- I have moved declarations of the
header and all the emission functions there.
Reviewers: JDevlieghere, aprantl, probinson, dblaikie
Subscribers: echristo, clayborg, vleschuk, llvm-commits
Differential Revision: https://reviews.llvm.org/D43285
llvm-svn: 325516
2018-02-19 16:12:20 +00:00
|
|
|
Header.emit(Asm);
|
|
|
|
HeaderData.emit(Asm);
|
|
|
|
emitBuckets();
|
|
|
|
emitHashes();
|
|
|
|
emitOffsets(SecBegin);
|
|
|
|
emitData();
|
2011-11-07 09:18:42 +00:00
|
|
|
}
|
|
|
|
|
2023-10-25 12:39:28 -07:00
|
|
|
DWARF5AccelTableData::DWARF5AccelTableData(const DIE &Die,
|
2023-11-18 06:36:33 -08:00
|
|
|
const uint32_t UnitID,
|
|
|
|
const bool IsTU)
|
2024-03-13 07:03:15 -07:00
|
|
|
: OffsetVal(&Die), DieTag(Die.getTag()), AbbrevNumber(0), IsTU(IsTU),
|
|
|
|
UnitID(UnitID) {}
|
2023-10-25 12:39:28 -07:00
|
|
|
|
2024-01-05 11:01:19 -03:00
|
|
|
void Dwarf5AccelTableWriter::Header::emit(Dwarf5AccelTableWriter &Ctx) {
|
2018-04-09 14:38:53 +00:00
|
|
|
assert(CompUnitCount > 0 && "Index must have at least one CU.");
|
|
|
|
|
2018-04-04 14:42:14 +00:00
|
|
|
AsmPrinter *Asm = Ctx.Asm;
|
2021-02-25 20:39:45 -05:00
|
|
|
Ctx.ContributionEnd =
|
|
|
|
Asm->emitDwarfUnitLength("names", "Header: unit length");
|
2018-04-04 14:42:14 +00:00
|
|
|
Asm->OutStreamer->AddComment("Header: version");
|
|
|
|
Asm->emitInt16(Version);
|
|
|
|
Asm->OutStreamer->AddComment("Header: padding");
|
|
|
|
Asm->emitInt16(Padding);
|
|
|
|
Asm->OutStreamer->AddComment("Header: compilation unit count");
|
|
|
|
Asm->emitInt32(CompUnitCount);
|
|
|
|
Asm->OutStreamer->AddComment("Header: local type unit count");
|
|
|
|
Asm->emitInt32(LocalTypeUnitCount);
|
|
|
|
Asm->OutStreamer->AddComment("Header: foreign type unit count");
|
|
|
|
Asm->emitInt32(ForeignTypeUnitCount);
|
|
|
|
Asm->OutStreamer->AddComment("Header: bucket count");
|
|
|
|
Asm->emitInt32(BucketCount);
|
|
|
|
Asm->OutStreamer->AddComment("Header: name count");
|
|
|
|
Asm->emitInt32(NameCount);
|
|
|
|
Asm->OutStreamer->AddComment("Header: abbreviation table size");
|
2020-02-13 13:26:21 -08:00
|
|
|
Asm->emitLabelDifference(Ctx.AbbrevEnd, Ctx.AbbrevStart, sizeof(uint32_t));
|
2018-04-04 14:42:14 +00:00
|
|
|
Asm->OutStreamer->AddComment("Header: augmentation string size");
|
|
|
|
assert(AugmentationStringSize % 4 == 0);
|
|
|
|
Asm->emitInt32(AugmentationStringSize);
|
|
|
|
Asm->OutStreamer->AddComment("Header: augmentation string");
|
2020-02-14 18:16:24 -08:00
|
|
|
Asm->OutStreamer->emitBytes({AugmentationString, AugmentationStringSize});
|
2018-04-04 14:42:14 +00:00
|
|
|
}
|
|
|
|
|
[AsmPrinter][DebugNames] Implement DW_IDX_parent entries (#77457)
This implements the ideas discussed in [1].
To summarize, this commit changes AsmPrinter so that it outputs
DW_IDX_parent information for debug_name entries. It will enable
debuggers to speed up queries for fully qualified types (based on a
DWARFDeclContext) significantly, as debuggers will no longer need to
parse the entire CU in order to inspect the parent chain of a DIE.
Instead, a debugger can simply take the parent DIE offset from the
accelerator table and peek at its name in the debug_info/debug_str
sections.
The implementation uses two types of DW_FORM for the DW_IDX_parent
attribute:
1. DW_FORM_ref4, which points to the accelerator table entry for the
parent.
2. DW_FORM_flag_present, when the entry has a parent that is not in the
table (that is, the parent doesn't have a name, or isn't allowed to be
in the table as per the DWARF spec). This is space-efficient, since it
takes 0 bytes.
The implementation works by:
1. Changing how abbreviations are encoded (so that they encode which
form, if
any, was used to encode IDX_Parent)
2. Creating an MCLabel per accelerator table entry, so that they may be
referred by IDX_parent references.
When all patches related to this are merged, we are able to show that
evaluating an expression such as:
```
lldb --batch -o 'b CodeGenFunction::GenerateCode' -o run -o 'expr Fn' -- \
clang++ -c -g test.cpp -o /dev/null
```
is far faster: from ~5000 ms to ~1500ms.
Building llvm-project + clang with and without this patch, and looking
at its impact on object file size:
```
ls -la $(find build_stage2_Debug_idx_parent_assert_dwarf5 -name \*.cpp.o) | awk '{s+=$5} END {printf "%\047d\n", s}'
11,507,327,592
-la $(find build_stage2_Debug_no_idx_parent_assert_dwarf5 -name \*.cpp.o) | awk '{s+=$5} END {printf "%\047d\n", s}'
11,436,446,616
```
That is, an increase of 0.62% in total object file size.
Looking only at debug_names:
```
$stage1_build/bin/llvm-objdump --section-headers $(find build_stage2_Debug_idx_parent_assert_dwarf5 -name \*.cpp.o) | grep __debug_names | awk '{s+="0x"$3} END {printf "%\047d\n", s}'
440,772,348
$stage1_build/bin/llvm-objdump --section-headers $(find build_stage2_Debug_no_idx_parent_assert_dwarf5 -name \*.cpp.o) | grep __debug_names | awk '{s+="0x"$3} END {printf "%\047d\n", s}'
369,867,920
```
That is an increase of 19%.
DWARF Linkers need to be changed in order to support this. This commit
already brings support to "base" linker, but it does not attempt to
modify the parallel linker. Accelerator entries refer to the
corresponding DIE offset, and this patch also requires the parent DIE
offset -- it's not clear how the parallel linker can access this. It may
be obvious to someone familiar with it, but it would be nice to get help
from its authors.
[1]:
https://discourse.llvm.org/t/rfc-improve-dwarf-5-debug-names-type-lookup-parsing-speed/74151/
2024-01-19 09:19:09 -08:00
|
|
|
std::optional<uint64_t>
|
|
|
|
DWARF5AccelTableData::getDefiningParentDieOffset(const DIE &Die) {
|
|
|
|
if (auto *Parent = Die.getParent();
|
|
|
|
Parent && !Parent->findAttribute(dwarf::Attribute::DW_AT_declaration))
|
|
|
|
return Parent->getOffset();
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
|
|
|
|
static std::optional<dwarf::Form>
|
|
|
|
getFormForIdxParent(const DenseSet<OffsetAndUnitID> &IndexedOffsets,
|
|
|
|
std::optional<OffsetAndUnitID> ParentOffset) {
|
|
|
|
// No parent information
|
|
|
|
if (!ParentOffset)
|
|
|
|
return std::nullopt;
|
|
|
|
// Parent is indexed by this table.
|
|
|
|
if (IndexedOffsets.contains(*ParentOffset))
|
|
|
|
return dwarf::Form::DW_FORM_ref4;
|
|
|
|
// Parent is not indexed by this table.
|
|
|
|
return dwarf::Form::DW_FORM_flag_present;
|
|
|
|
}
|
|
|
|
|
2024-02-14 12:22:53 -08:00
|
|
|
void DebugNamesAbbrev::Profile(FoldingSetNodeID &ID) const {
|
|
|
|
ID.AddInteger(DieTag);
|
|
|
|
for (const DebugNamesAbbrev::AttributeEncoding &Enc : AttrVect) {
|
|
|
|
ID.AddInteger(Enc.Index);
|
|
|
|
ID.AddInteger(Enc.Form);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-01-05 11:01:19 -03:00
|
|
|
void Dwarf5AccelTableWriter::populateAbbrevsMap() {
|
2018-04-04 14:42:14 +00:00
|
|
|
for (auto &Bucket : Contents.getBuckets()) {
|
|
|
|
for (auto *Hash : Bucket) {
|
2024-01-08 17:04:07 -03:00
|
|
|
for (auto *Value : Hash->getValues<DWARF5AccelTableData *>()) {
|
2023-11-18 06:36:33 -08:00
|
|
|
std::optional<DWARF5AccelTable::UnitIndexAndEncoding> EntryRet =
|
2024-01-08 17:04:07 -03:00
|
|
|
getIndexForEntry(*Value);
|
[AsmPrinter][DebugNames] Implement DW_IDX_parent entries (#77457)
This implements the ideas discussed in [1].
To summarize, this commit changes AsmPrinter so that it outputs
DW_IDX_parent information for debug_name entries. It will enable
debuggers to speed up queries for fully qualified types (based on a
DWARFDeclContext) significantly, as debuggers will no longer need to
parse the entire CU in order to inspect the parent chain of a DIE.
Instead, a debugger can simply take the parent DIE offset from the
accelerator table and peek at its name in the debug_info/debug_str
sections.
The implementation uses two types of DW_FORM for the DW_IDX_parent
attribute:
1. DW_FORM_ref4, which points to the accelerator table entry for the
parent.
2. DW_FORM_flag_present, when the entry has a parent that is not in the
table (that is, the parent doesn't have a name, or isn't allowed to be
in the table as per the DWARF spec). This is space-efficient, since it
takes 0 bytes.
The implementation works by:
1. Changing how abbreviations are encoded (so that they encode which
form, if
any, was used to encode IDX_Parent)
2. Creating an MCLabel per accelerator table entry, so that they may be
referred by IDX_parent references.
When all patches related to this are merged, we are able to show that
evaluating an expression such as:
```
lldb --batch -o 'b CodeGenFunction::GenerateCode' -o run -o 'expr Fn' -- \
clang++ -c -g test.cpp -o /dev/null
```
is far faster: from ~5000 ms to ~1500ms.
Building llvm-project + clang with and without this patch, and looking
at its impact on object file size:
```
ls -la $(find build_stage2_Debug_idx_parent_assert_dwarf5 -name \*.cpp.o) | awk '{s+=$5} END {printf "%\047d\n", s}'
11,507,327,592
-la $(find build_stage2_Debug_no_idx_parent_assert_dwarf5 -name \*.cpp.o) | awk '{s+=$5} END {printf "%\047d\n", s}'
11,436,446,616
```
That is, an increase of 0.62% in total object file size.
Looking only at debug_names:
```
$stage1_build/bin/llvm-objdump --section-headers $(find build_stage2_Debug_idx_parent_assert_dwarf5 -name \*.cpp.o) | grep __debug_names | awk '{s+="0x"$3} END {printf "%\047d\n", s}'
440,772,348
$stage1_build/bin/llvm-objdump --section-headers $(find build_stage2_Debug_no_idx_parent_assert_dwarf5 -name \*.cpp.o) | grep __debug_names | awk '{s+="0x"$3} END {printf "%\047d\n", s}'
369,867,920
```
That is an increase of 19%.
DWARF Linkers need to be changed in order to support this. This commit
already brings support to "base" linker, but it does not attempt to
modify the parallel linker. Accelerator entries refer to the
corresponding DIE offset, and this patch also requires the parent DIE
offset -- it's not clear how the parallel linker can access this. It may
be obvious to someone familiar with it, but it would be nice to get help
from its authors.
[1]:
https://discourse.llvm.org/t/rfc-improve-dwarf-5-debug-names-type-lookup-parsing-speed/74151/
2024-01-19 09:19:09 -08:00
|
|
|
std::optional<dwarf::Form> MaybeParentForm = getFormForIdxParent(
|
|
|
|
IndexedOffsets, Value->getParentDieOffsetAndUnitID());
|
2024-02-14 12:22:53 -08:00
|
|
|
DebugNamesAbbrev Abbrev(Value->getDieTag());
|
|
|
|
if (EntryRet)
|
|
|
|
Abbrev.addAttribute(EntryRet->Encoding);
|
|
|
|
Abbrev.addAttribute({dwarf::DW_IDX_die_offset, dwarf::DW_FORM_ref4});
|
|
|
|
if (MaybeParentForm)
|
|
|
|
Abbrev.addAttribute({dwarf::DW_IDX_parent, *MaybeParentForm});
|
|
|
|
FoldingSetNodeID ID;
|
|
|
|
Abbrev.Profile(ID);
|
|
|
|
void *InsertPos;
|
|
|
|
if (DebugNamesAbbrev *Existing =
|
|
|
|
AbbreviationsSet.FindNodeOrInsertPos(ID, InsertPos)) {
|
|
|
|
Value->setAbbrevNumber(Existing->getNumber());
|
|
|
|
continue;
|
2023-11-18 06:36:33 -08:00
|
|
|
}
|
2024-02-14 12:22:53 -08:00
|
|
|
DebugNamesAbbrev *NewAbbrev =
|
|
|
|
new (Alloc) DebugNamesAbbrev(std::move(Abbrev));
|
|
|
|
AbbreviationsVector.push_back(NewAbbrev);
|
|
|
|
NewAbbrev->setNumber(AbbreviationsVector.size());
|
|
|
|
AbbreviationsSet.InsertNode(NewAbbrev, InsertPos);
|
|
|
|
Value->setAbbrevNumber(NewAbbrev->getNumber());
|
2018-04-04 14:42:14 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-01-05 11:01:19 -03:00
|
|
|
void Dwarf5AccelTableWriter::emitCUList() const {
|
2018-07-10 16:18:56 +00:00
|
|
|
for (const auto &CU : enumerate(CompUnits)) {
|
|
|
|
Asm->OutStreamer->AddComment("Compilation unit " + Twine(CU.index()));
|
2023-07-04 13:24:50 +02:00
|
|
|
if (std::holds_alternative<MCSymbol *>(CU.value()))
|
|
|
|
Asm->emitDwarfSymbolReference(std::get<MCSymbol *>(CU.value()));
|
|
|
|
else
|
|
|
|
Asm->emitDwarfLengthOrOffset(std::get<uint64_t>(CU.value()));
|
2018-04-04 14:42:14 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-01-05 11:01:19 -03:00
|
|
|
void Dwarf5AccelTableWriter::emitTUList() const {
|
2023-11-18 06:36:33 -08:00
|
|
|
for (const auto &TU : enumerate(TypeUnits)) {
|
|
|
|
Asm->OutStreamer->AddComment("Type unit " + Twine(TU.index()));
|
|
|
|
if (std::holds_alternative<MCSymbol *>(TU.value()))
|
|
|
|
Asm->emitDwarfSymbolReference(std::get<MCSymbol *>(TU.value()));
|
2023-12-04 13:56:21 -08:00
|
|
|
else if (IsSplitDwarf)
|
|
|
|
Asm->emitInt64(std::get<uint64_t>(TU.value()));
|
2023-11-18 06:36:33 -08:00
|
|
|
else
|
|
|
|
Asm->emitDwarfLengthOrOffset(std::get<uint64_t>(TU.value()));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-01-05 11:01:19 -03:00
|
|
|
void Dwarf5AccelTableWriter::emitBuckets() const {
|
2018-04-04 14:42:14 +00:00
|
|
|
uint32_t Index = 1;
|
|
|
|
for (const auto &Bucket : enumerate(Contents.getBuckets())) {
|
|
|
|
Asm->OutStreamer->AddComment("Bucket " + Twine(Bucket.index()));
|
|
|
|
Asm->emitInt32(Bucket.value().empty() ? 0 : Index);
|
|
|
|
Index += Bucket.value().size();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-01-05 11:01:19 -03:00
|
|
|
void Dwarf5AccelTableWriter::emitStringOffsets() const {
|
2018-04-04 14:42:14 +00:00
|
|
|
for (const auto &Bucket : enumerate(Contents.getBuckets())) {
|
|
|
|
for (auto *Hash : Bucket.value()) {
|
|
|
|
DwarfStringPoolEntryRef String = Hash->Name;
|
|
|
|
Asm->OutStreamer->AddComment("String in Bucket " + Twine(Bucket.index()) +
|
|
|
|
": " + String.getString());
|
|
|
|
Asm->emitDwarfStringOffset(String);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-01-05 11:01:19 -03:00
|
|
|
void Dwarf5AccelTableWriter::emitAbbrevs() const {
|
2020-02-14 19:21:58 -08:00
|
|
|
Asm->OutStreamer->emitLabel(AbbrevStart);
|
2024-02-14 12:22:53 -08:00
|
|
|
for (const DebugNamesAbbrev *Abbrev : AbbreviationsVector) {
|
2018-04-04 14:42:14 +00:00
|
|
|
Asm->OutStreamer->AddComment("Abbrev code");
|
2024-02-14 12:22:53 -08:00
|
|
|
Asm->emitULEB128(Abbrev->getNumber());
|
|
|
|
Asm->OutStreamer->AddComment(dwarf::TagString(Abbrev->getDieTag()));
|
|
|
|
Asm->emitULEB128(Abbrev->getDieTag());
|
|
|
|
for (const DebugNamesAbbrev::AttributeEncoding &AttrEnc :
|
|
|
|
Abbrev->getAttributes()) {
|
2020-02-13 13:26:21 -08:00
|
|
|
Asm->emitULEB128(AttrEnc.Index, dwarf::IndexString(AttrEnc.Index).data());
|
|
|
|
Asm->emitULEB128(AttrEnc.Form,
|
2018-04-04 14:42:14 +00:00
|
|
|
dwarf::FormEncodingString(AttrEnc.Form).data());
|
|
|
|
}
|
2020-02-13 13:26:21 -08:00
|
|
|
Asm->emitULEB128(0, "End of abbrev");
|
|
|
|
Asm->emitULEB128(0, "End of abbrev");
|
2018-04-04 14:42:14 +00:00
|
|
|
}
|
2020-02-13 13:26:21 -08:00
|
|
|
Asm->emitULEB128(0, "End of abbrev list");
|
2020-02-14 19:21:58 -08:00
|
|
|
Asm->OutStreamer->emitLabel(AbbrevEnd);
|
2018-04-04 14:42:14 +00:00
|
|
|
}
|
|
|
|
|
2024-01-05 11:01:19 -03:00
|
|
|
void Dwarf5AccelTableWriter::emitEntry(
|
[AsmPrinter][DebugNames] Implement DW_IDX_parent entries (#77457)
This implements the ideas discussed in [1].
To summarize, this commit changes AsmPrinter so that it outputs
DW_IDX_parent information for debug_name entries. It will enable
debuggers to speed up queries for fully qualified types (based on a
DWARFDeclContext) significantly, as debuggers will no longer need to
parse the entire CU in order to inspect the parent chain of a DIE.
Instead, a debugger can simply take the parent DIE offset from the
accelerator table and peek at its name in the debug_info/debug_str
sections.
The implementation uses two types of DW_FORM for the DW_IDX_parent
attribute:
1. DW_FORM_ref4, which points to the accelerator table entry for the
parent.
2. DW_FORM_flag_present, when the entry has a parent that is not in the
table (that is, the parent doesn't have a name, or isn't allowed to be
in the table as per the DWARF spec). This is space-efficient, since it
takes 0 bytes.
The implementation works by:
1. Changing how abbreviations are encoded (so that they encode which
form, if
any, was used to encode IDX_Parent)
2. Creating an MCLabel per accelerator table entry, so that they may be
referred by IDX_parent references.
When all patches related to this are merged, we are able to show that
evaluating an expression such as:
```
lldb --batch -o 'b CodeGenFunction::GenerateCode' -o run -o 'expr Fn' -- \
clang++ -c -g test.cpp -o /dev/null
```
is far faster: from ~5000 ms to ~1500ms.
Building llvm-project + clang with and without this patch, and looking
at its impact on object file size:
```
ls -la $(find build_stage2_Debug_idx_parent_assert_dwarf5 -name \*.cpp.o) | awk '{s+=$5} END {printf "%\047d\n", s}'
11,507,327,592
-la $(find build_stage2_Debug_no_idx_parent_assert_dwarf5 -name \*.cpp.o) | awk '{s+=$5} END {printf "%\047d\n", s}'
11,436,446,616
```
That is, an increase of 0.62% in total object file size.
Looking only at debug_names:
```
$stage1_build/bin/llvm-objdump --section-headers $(find build_stage2_Debug_idx_parent_assert_dwarf5 -name \*.cpp.o) | grep __debug_names | awk '{s+="0x"$3} END {printf "%\047d\n", s}'
440,772,348
$stage1_build/bin/llvm-objdump --section-headers $(find build_stage2_Debug_no_idx_parent_assert_dwarf5 -name \*.cpp.o) | grep __debug_names | awk '{s+="0x"$3} END {printf "%\047d\n", s}'
369,867,920
```
That is an increase of 19%.
DWARF Linkers need to be changed in order to support this. This commit
already brings support to "base" linker, but it does not attempt to
modify the parallel linker. Accelerator entries refer to the
corresponding DIE offset, and this patch also requires the parent DIE
offset -- it's not clear how the parallel linker can access this. It may
be obvious to someone familiar with it, but it would be nice to get help
from its authors.
[1]:
https://discourse.llvm.org/t/rfc-improve-dwarf-5-debug-names-type-lookup-parsing-speed/74151/
2024-01-19 09:19:09 -08:00
|
|
|
const DWARF5AccelTableData &Entry,
|
|
|
|
const DenseMap<OffsetAndUnitID, MCSymbol *> &DIEOffsetToAccelEntryLabel,
|
2024-02-14 12:22:53 -08:00
|
|
|
DenseSet<MCSymbol *> &EmittedAccelEntrySymbols) {
|
|
|
|
unsigned AbbrevIndex = Entry.getAbbrevNumber() - 1;
|
|
|
|
assert(AbbrevIndex < AbbreviationsVector.size() &&
|
|
|
|
"Entry abbrev index is outside of abbreviations vector range.");
|
|
|
|
DebugNamesAbbrev *Abbrev = AbbreviationsVector[AbbrevIndex];
|
2023-11-18 06:36:33 -08:00
|
|
|
std::optional<DWARF5AccelTable::UnitIndexAndEncoding> EntryRet =
|
|
|
|
getIndexForEntry(Entry);
|
[AsmPrinter][DebugNames] Implement DW_IDX_parent entries (#77457)
This implements the ideas discussed in [1].
To summarize, this commit changes AsmPrinter so that it outputs
DW_IDX_parent information for debug_name entries. It will enable
debuggers to speed up queries for fully qualified types (based on a
DWARFDeclContext) significantly, as debuggers will no longer need to
parse the entire CU in order to inspect the parent chain of a DIE.
Instead, a debugger can simply take the parent DIE offset from the
accelerator table and peek at its name in the debug_info/debug_str
sections.
The implementation uses two types of DW_FORM for the DW_IDX_parent
attribute:
1. DW_FORM_ref4, which points to the accelerator table entry for the
parent.
2. DW_FORM_flag_present, when the entry has a parent that is not in the
table (that is, the parent doesn't have a name, or isn't allowed to be
in the table as per the DWARF spec). This is space-efficient, since it
takes 0 bytes.
The implementation works by:
1. Changing how abbreviations are encoded (so that they encode which
form, if
any, was used to encode IDX_Parent)
2. Creating an MCLabel per accelerator table entry, so that they may be
referred by IDX_parent references.
When all patches related to this are merged, we are able to show that
evaluating an expression such as:
```
lldb --batch -o 'b CodeGenFunction::GenerateCode' -o run -o 'expr Fn' -- \
clang++ -c -g test.cpp -o /dev/null
```
is far faster: from ~5000 ms to ~1500ms.
Building llvm-project + clang with and without this patch, and looking
at its impact on object file size:
```
ls -la $(find build_stage2_Debug_idx_parent_assert_dwarf5 -name \*.cpp.o) | awk '{s+=$5} END {printf "%\047d\n", s}'
11,507,327,592
-la $(find build_stage2_Debug_no_idx_parent_assert_dwarf5 -name \*.cpp.o) | awk '{s+=$5} END {printf "%\047d\n", s}'
11,436,446,616
```
That is, an increase of 0.62% in total object file size.
Looking only at debug_names:
```
$stage1_build/bin/llvm-objdump --section-headers $(find build_stage2_Debug_idx_parent_assert_dwarf5 -name \*.cpp.o) | grep __debug_names | awk '{s+="0x"$3} END {printf "%\047d\n", s}'
440,772,348
$stage1_build/bin/llvm-objdump --section-headers $(find build_stage2_Debug_no_idx_parent_assert_dwarf5 -name \*.cpp.o) | grep __debug_names | awk '{s+="0x"$3} END {printf "%\047d\n", s}'
369,867,920
```
That is an increase of 19%.
DWARF Linkers need to be changed in order to support this. This commit
already brings support to "base" linker, but it does not attempt to
modify the parallel linker. Accelerator entries refer to the
corresponding DIE offset, and this patch also requires the parent DIE
offset -- it's not clear how the parallel linker can access this. It may
be obvious to someone familiar with it, but it would be nice to get help
from its authors.
[1]:
https://discourse.llvm.org/t/rfc-improve-dwarf-5-debug-names-type-lookup-parsing-speed/74151/
2024-01-19 09:19:09 -08:00
|
|
|
std::optional<OffsetAndUnitID> MaybeParentOffset =
|
|
|
|
Entry.getParentDieOffsetAndUnitID();
|
|
|
|
auto EntrySymbolIt =
|
|
|
|
DIEOffsetToAccelEntryLabel.find(Entry.getDieOffsetAndUnitID());
|
|
|
|
assert(EntrySymbolIt != DIEOffsetToAccelEntryLabel.end());
|
|
|
|
MCSymbol *EntrySymbol = EntrySymbolIt->getSecond();
|
|
|
|
|
|
|
|
// Emit the label for this Entry, so that IDX_parents may refer to it.
|
|
|
|
// Note: a DIE may have multiple accelerator Entries; this check avoids
|
|
|
|
// creating/emitting multiple labels for the same DIE.
|
|
|
|
if (EmittedAccelEntrySymbols.insert(EntrySymbol).second)
|
|
|
|
Asm->OutStreamer->emitLabel(EntrySymbol);
|
|
|
|
|
2024-02-14 12:22:53 -08:00
|
|
|
Asm->emitULEB128(Entry.getAbbrevNumber(), "Abbreviation code");
|
2023-11-18 06:36:33 -08:00
|
|
|
|
2024-02-14 12:22:53 -08:00
|
|
|
for (const DebugNamesAbbrev::AttributeEncoding &AttrEnc :
|
|
|
|
Abbrev->getAttributes()) {
|
2018-04-04 14:42:14 +00:00
|
|
|
Asm->OutStreamer->AddComment(dwarf::IndexString(AttrEnc.Index));
|
|
|
|
switch (AttrEnc.Index) {
|
2023-11-18 06:36:33 -08:00
|
|
|
case dwarf::DW_IDX_compile_unit:
|
|
|
|
case dwarf::DW_IDX_type_unit: {
|
|
|
|
DIEInteger ID(EntryRet->Index);
|
2020-02-14 22:40:47 -08:00
|
|
|
ID.emitValue(Asm, AttrEnc.Form);
|
2018-04-04 14:42:14 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case dwarf::DW_IDX_die_offset:
|
|
|
|
assert(AttrEnc.Form == dwarf::DW_FORM_ref4);
|
2018-07-16 10:52:27 +00:00
|
|
|
Asm->emitInt32(Entry.getDieOffset());
|
2018-04-04 14:42:14 +00:00
|
|
|
break;
|
[AsmPrinter][DebugNames] Implement DW_IDX_parent entries (#77457)
This implements the ideas discussed in [1].
To summarize, this commit changes AsmPrinter so that it outputs
DW_IDX_parent information for debug_name entries. It will enable
debuggers to speed up queries for fully qualified types (based on a
DWARFDeclContext) significantly, as debuggers will no longer need to
parse the entire CU in order to inspect the parent chain of a DIE.
Instead, a debugger can simply take the parent DIE offset from the
accelerator table and peek at its name in the debug_info/debug_str
sections.
The implementation uses two types of DW_FORM for the DW_IDX_parent
attribute:
1. DW_FORM_ref4, which points to the accelerator table entry for the
parent.
2. DW_FORM_flag_present, when the entry has a parent that is not in the
table (that is, the parent doesn't have a name, or isn't allowed to be
in the table as per the DWARF spec). This is space-efficient, since it
takes 0 bytes.
The implementation works by:
1. Changing how abbreviations are encoded (so that they encode which
form, if
any, was used to encode IDX_Parent)
2. Creating an MCLabel per accelerator table entry, so that they may be
referred by IDX_parent references.
When all patches related to this are merged, we are able to show that
evaluating an expression such as:
```
lldb --batch -o 'b CodeGenFunction::GenerateCode' -o run -o 'expr Fn' -- \
clang++ -c -g test.cpp -o /dev/null
```
is far faster: from ~5000 ms to ~1500ms.
Building llvm-project + clang with and without this patch, and looking
at its impact on object file size:
```
ls -la $(find build_stage2_Debug_idx_parent_assert_dwarf5 -name \*.cpp.o) | awk '{s+=$5} END {printf "%\047d\n", s}'
11,507,327,592
-la $(find build_stage2_Debug_no_idx_parent_assert_dwarf5 -name \*.cpp.o) | awk '{s+=$5} END {printf "%\047d\n", s}'
11,436,446,616
```
That is, an increase of 0.62% in total object file size.
Looking only at debug_names:
```
$stage1_build/bin/llvm-objdump --section-headers $(find build_stage2_Debug_idx_parent_assert_dwarf5 -name \*.cpp.o) | grep __debug_names | awk '{s+="0x"$3} END {printf "%\047d\n", s}'
440,772,348
$stage1_build/bin/llvm-objdump --section-headers $(find build_stage2_Debug_no_idx_parent_assert_dwarf5 -name \*.cpp.o) | grep __debug_names | awk '{s+="0x"$3} END {printf "%\047d\n", s}'
369,867,920
```
That is an increase of 19%.
DWARF Linkers need to be changed in order to support this. This commit
already brings support to "base" linker, but it does not attempt to
modify the parallel linker. Accelerator entries refer to the
corresponding DIE offset, and this patch also requires the parent DIE
offset -- it's not clear how the parallel linker can access this. It may
be obvious to someone familiar with it, but it would be nice to get help
from its authors.
[1]:
https://discourse.llvm.org/t/rfc-improve-dwarf-5-debug-names-type-lookup-parsing-speed/74151/
2024-01-19 09:19:09 -08:00
|
|
|
case dwarf::DW_IDX_parent: {
|
|
|
|
if (AttrEnc.Form == dwarf::Form::DW_FORM_flag_present)
|
|
|
|
break;
|
|
|
|
auto ParentSymbolIt = DIEOffsetToAccelEntryLabel.find(*MaybeParentOffset);
|
|
|
|
assert(ParentSymbolIt != DIEOffsetToAccelEntryLabel.end());
|
|
|
|
Asm->emitLabelDifference(ParentSymbolIt->getSecond(), EntryPool, 4);
|
|
|
|
break;
|
|
|
|
}
|
2018-04-04 14:42:14 +00:00
|
|
|
default:
|
|
|
|
llvm_unreachable("Unexpected index attribute!");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
[AsmPrinter][DebugNames] Implement DW_IDX_parent entries (#77457)
This implements the ideas discussed in [1].
To summarize, this commit changes AsmPrinter so that it outputs
DW_IDX_parent information for debug_name entries. It will enable
debuggers to speed up queries for fully qualified types (based on a
DWARFDeclContext) significantly, as debuggers will no longer need to
parse the entire CU in order to inspect the parent chain of a DIE.
Instead, a debugger can simply take the parent DIE offset from the
accelerator table and peek at its name in the debug_info/debug_str
sections.
The implementation uses two types of DW_FORM for the DW_IDX_parent
attribute:
1. DW_FORM_ref4, which points to the accelerator table entry for the
parent.
2. DW_FORM_flag_present, when the entry has a parent that is not in the
table (that is, the parent doesn't have a name, or isn't allowed to be
in the table as per the DWARF spec). This is space-efficient, since it
takes 0 bytes.
The implementation works by:
1. Changing how abbreviations are encoded (so that they encode which
form, if
any, was used to encode IDX_Parent)
2. Creating an MCLabel per accelerator table entry, so that they may be
referred by IDX_parent references.
When all patches related to this are merged, we are able to show that
evaluating an expression such as:
```
lldb --batch -o 'b CodeGenFunction::GenerateCode' -o run -o 'expr Fn' -- \
clang++ -c -g test.cpp -o /dev/null
```
is far faster: from ~5000 ms to ~1500ms.
Building llvm-project + clang with and without this patch, and looking
at its impact on object file size:
```
ls -la $(find build_stage2_Debug_idx_parent_assert_dwarf5 -name \*.cpp.o) | awk '{s+=$5} END {printf "%\047d\n", s}'
11,507,327,592
-la $(find build_stage2_Debug_no_idx_parent_assert_dwarf5 -name \*.cpp.o) | awk '{s+=$5} END {printf "%\047d\n", s}'
11,436,446,616
```
That is, an increase of 0.62% in total object file size.
Looking only at debug_names:
```
$stage1_build/bin/llvm-objdump --section-headers $(find build_stage2_Debug_idx_parent_assert_dwarf5 -name \*.cpp.o) | grep __debug_names | awk '{s+="0x"$3} END {printf "%\047d\n", s}'
440,772,348
$stage1_build/bin/llvm-objdump --section-headers $(find build_stage2_Debug_no_idx_parent_assert_dwarf5 -name \*.cpp.o) | grep __debug_names | awk '{s+="0x"$3} END {printf "%\047d\n", s}'
369,867,920
```
That is an increase of 19%.
DWARF Linkers need to be changed in order to support this. This commit
already brings support to "base" linker, but it does not attempt to
modify the parallel linker. Accelerator entries refer to the
corresponding DIE offset, and this patch also requires the parent DIE
offset -- it's not clear how the parallel linker can access this. It may
be obvious to someone familiar with it, but it would be nice to get help
from its authors.
[1]:
https://discourse.llvm.org/t/rfc-improve-dwarf-5-debug-names-type-lookup-parsing-speed/74151/
2024-01-19 09:19:09 -08:00
|
|
|
void Dwarf5AccelTableWriter::emitData() {
|
|
|
|
DenseMap<OffsetAndUnitID, MCSymbol *> DIEOffsetToAccelEntryLabel;
|
|
|
|
|
|
|
|
for (OffsetAndUnitID Offset : IndexedOffsets)
|
|
|
|
DIEOffsetToAccelEntryLabel.insert({Offset, Asm->createTempSymbol("")});
|
|
|
|
|
2020-02-14 19:21:58 -08:00
|
|
|
Asm->OutStreamer->emitLabel(EntryPool);
|
[AsmPrinter][DebugNames] Implement DW_IDX_parent entries (#77457)
This implements the ideas discussed in [1].
To summarize, this commit changes AsmPrinter so that it outputs
DW_IDX_parent information for debug_name entries. It will enable
debuggers to speed up queries for fully qualified types (based on a
DWARFDeclContext) significantly, as debuggers will no longer need to
parse the entire CU in order to inspect the parent chain of a DIE.
Instead, a debugger can simply take the parent DIE offset from the
accelerator table and peek at its name in the debug_info/debug_str
sections.
The implementation uses two types of DW_FORM for the DW_IDX_parent
attribute:
1. DW_FORM_ref4, which points to the accelerator table entry for the
parent.
2. DW_FORM_flag_present, when the entry has a parent that is not in the
table (that is, the parent doesn't have a name, or isn't allowed to be
in the table as per the DWARF spec). This is space-efficient, since it
takes 0 bytes.
The implementation works by:
1. Changing how abbreviations are encoded (so that they encode which
form, if
any, was used to encode IDX_Parent)
2. Creating an MCLabel per accelerator table entry, so that they may be
referred by IDX_parent references.
When all patches related to this are merged, we are able to show that
evaluating an expression such as:
```
lldb --batch -o 'b CodeGenFunction::GenerateCode' -o run -o 'expr Fn' -- \
clang++ -c -g test.cpp -o /dev/null
```
is far faster: from ~5000 ms to ~1500ms.
Building llvm-project + clang with and without this patch, and looking
at its impact on object file size:
```
ls -la $(find build_stage2_Debug_idx_parent_assert_dwarf5 -name \*.cpp.o) | awk '{s+=$5} END {printf "%\047d\n", s}'
11,507,327,592
-la $(find build_stage2_Debug_no_idx_parent_assert_dwarf5 -name \*.cpp.o) | awk '{s+=$5} END {printf "%\047d\n", s}'
11,436,446,616
```
That is, an increase of 0.62% in total object file size.
Looking only at debug_names:
```
$stage1_build/bin/llvm-objdump --section-headers $(find build_stage2_Debug_idx_parent_assert_dwarf5 -name \*.cpp.o) | grep __debug_names | awk '{s+="0x"$3} END {printf "%\047d\n", s}'
440,772,348
$stage1_build/bin/llvm-objdump --section-headers $(find build_stage2_Debug_no_idx_parent_assert_dwarf5 -name \*.cpp.o) | grep __debug_names | awk '{s+="0x"$3} END {printf "%\047d\n", s}'
369,867,920
```
That is an increase of 19%.
DWARF Linkers need to be changed in order to support this. This commit
already brings support to "base" linker, but it does not attempt to
modify the parallel linker. Accelerator entries refer to the
corresponding DIE offset, and this patch also requires the parent DIE
offset -- it's not clear how the parallel linker can access this. It may
be obvious to someone familiar with it, but it would be nice to get help
from its authors.
[1]:
https://discourse.llvm.org/t/rfc-improve-dwarf-5-debug-names-type-lookup-parsing-speed/74151/
2024-01-19 09:19:09 -08:00
|
|
|
DenseSet<MCSymbol *> EmittedAccelEntrySymbols;
|
2018-04-04 14:42:14 +00:00
|
|
|
for (auto &Bucket : Contents.getBuckets()) {
|
|
|
|
for (auto *Hash : Bucket) {
|
|
|
|
// Remember to emit the label for our offset.
|
2020-02-14 19:21:58 -08:00
|
|
|
Asm->OutStreamer->emitLabel(Hash->Sym);
|
[AsmPrinter][DebugNames] Implement DW_IDX_parent entries (#77457)
This implements the ideas discussed in [1].
To summarize, this commit changes AsmPrinter so that it outputs
DW_IDX_parent information for debug_name entries. It will enable
debuggers to speed up queries for fully qualified types (based on a
DWARFDeclContext) significantly, as debuggers will no longer need to
parse the entire CU in order to inspect the parent chain of a DIE.
Instead, a debugger can simply take the parent DIE offset from the
accelerator table and peek at its name in the debug_info/debug_str
sections.
The implementation uses two types of DW_FORM for the DW_IDX_parent
attribute:
1. DW_FORM_ref4, which points to the accelerator table entry for the
parent.
2. DW_FORM_flag_present, when the entry has a parent that is not in the
table (that is, the parent doesn't have a name, or isn't allowed to be
in the table as per the DWARF spec). This is space-efficient, since it
takes 0 bytes.
The implementation works by:
1. Changing how abbreviations are encoded (so that they encode which
form, if
any, was used to encode IDX_Parent)
2. Creating an MCLabel per accelerator table entry, so that they may be
referred by IDX_parent references.
When all patches related to this are merged, we are able to show that
evaluating an expression such as:
```
lldb --batch -o 'b CodeGenFunction::GenerateCode' -o run -o 'expr Fn' -- \
clang++ -c -g test.cpp -o /dev/null
```
is far faster: from ~5000 ms to ~1500ms.
Building llvm-project + clang with and without this patch, and looking
at its impact on object file size:
```
ls -la $(find build_stage2_Debug_idx_parent_assert_dwarf5 -name \*.cpp.o) | awk '{s+=$5} END {printf "%\047d\n", s}'
11,507,327,592
-la $(find build_stage2_Debug_no_idx_parent_assert_dwarf5 -name \*.cpp.o) | awk '{s+=$5} END {printf "%\047d\n", s}'
11,436,446,616
```
That is, an increase of 0.62% in total object file size.
Looking only at debug_names:
```
$stage1_build/bin/llvm-objdump --section-headers $(find build_stage2_Debug_idx_parent_assert_dwarf5 -name \*.cpp.o) | grep __debug_names | awk '{s+="0x"$3} END {printf "%\047d\n", s}'
440,772,348
$stage1_build/bin/llvm-objdump --section-headers $(find build_stage2_Debug_no_idx_parent_assert_dwarf5 -name \*.cpp.o) | grep __debug_names | awk '{s+="0x"$3} END {printf "%\047d\n", s}'
369,867,920
```
That is an increase of 19%.
DWARF Linkers need to be changed in order to support this. This commit
already brings support to "base" linker, but it does not attempt to
modify the parallel linker. Accelerator entries refer to the
corresponding DIE offset, and this patch also requires the parent DIE
offset -- it's not clear how the parallel linker can access this. It may
be obvious to someone familiar with it, but it would be nice to get help
from its authors.
[1]:
https://discourse.llvm.org/t/rfc-improve-dwarf-5-debug-names-type-lookup-parsing-speed/74151/
2024-01-19 09:19:09 -08:00
|
|
|
for (const auto *Value : Hash->getValues<DWARF5AccelTableData *>())
|
|
|
|
emitEntry(*Value, DIEOffsetToAccelEntryLabel, EmittedAccelEntrySymbols);
|
2018-04-04 14:42:14 +00:00
|
|
|
Asm->OutStreamer->AddComment("End of list: " + Hash->Name.getString());
|
2020-09-02 16:12:39 +07:00
|
|
|
Asm->emitInt8(0);
|
2018-04-04 14:42:14 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-01-05 11:01:19 -03:00
|
|
|
Dwarf5AccelTableWriter::Dwarf5AccelTableWriter(
|
2018-07-16 10:52:27 +00:00
|
|
|
AsmPrinter *Asm, const AccelTableBase &Contents,
|
2023-07-04 13:24:50 +02:00
|
|
|
ArrayRef<std::variant<MCSymbol *, uint64_t>> CompUnits,
|
2023-11-18 06:36:33 -08:00
|
|
|
ArrayRef<std::variant<MCSymbol *, uint64_t>> TypeUnits,
|
2024-01-05 11:01:19 -03:00
|
|
|
llvm::function_ref<std::optional<DWARF5AccelTable::UnitIndexAndEncoding>(
|
|
|
|
const DWARF5AccelTableData &)>
|
2023-12-04 13:56:21 -08:00
|
|
|
getIndexForEntry,
|
|
|
|
bool IsSplitDwarf)
|
2018-07-09 08:47:38 +00:00
|
|
|
: AccelTableWriter(Asm, Contents, false),
|
2023-12-04 13:56:21 -08:00
|
|
|
Header(CompUnits.size(), IsSplitDwarf ? 0 : TypeUnits.size(),
|
|
|
|
IsSplitDwarf ? TypeUnits.size() : 0, Contents.getBucketCount(),
|
2018-04-04 14:42:14 +00:00
|
|
|
Contents.getUniqueNameCount()),
|
2023-11-18 06:36:33 -08:00
|
|
|
CompUnits(CompUnits), TypeUnits(TypeUnits),
|
2023-12-04 13:56:21 -08:00
|
|
|
getIndexForEntry(std::move(getIndexForEntry)),
|
|
|
|
IsSplitDwarf(IsSplitDwarf) {
|
[AsmPrinter][DebugNames] Implement DW_IDX_parent entries (#77457)
This implements the ideas discussed in [1].
To summarize, this commit changes AsmPrinter so that it outputs
DW_IDX_parent information for debug_name entries. It will enable
debuggers to speed up queries for fully qualified types (based on a
DWARFDeclContext) significantly, as debuggers will no longer need to
parse the entire CU in order to inspect the parent chain of a DIE.
Instead, a debugger can simply take the parent DIE offset from the
accelerator table and peek at its name in the debug_info/debug_str
sections.
The implementation uses two types of DW_FORM for the DW_IDX_parent
attribute:
1. DW_FORM_ref4, which points to the accelerator table entry for the
parent.
2. DW_FORM_flag_present, when the entry has a parent that is not in the
table (that is, the parent doesn't have a name, or isn't allowed to be
in the table as per the DWARF spec). This is space-efficient, since it
takes 0 bytes.
The implementation works by:
1. Changing how abbreviations are encoded (so that they encode which
form, if
any, was used to encode IDX_Parent)
2. Creating an MCLabel per accelerator table entry, so that they may be
referred by IDX_parent references.
When all patches related to this are merged, we are able to show that
evaluating an expression such as:
```
lldb --batch -o 'b CodeGenFunction::GenerateCode' -o run -o 'expr Fn' -- \
clang++ -c -g test.cpp -o /dev/null
```
is far faster: from ~5000 ms to ~1500ms.
Building llvm-project + clang with and without this patch, and looking
at its impact on object file size:
```
ls -la $(find build_stage2_Debug_idx_parent_assert_dwarf5 -name \*.cpp.o) | awk '{s+=$5} END {printf "%\047d\n", s}'
11,507,327,592
-la $(find build_stage2_Debug_no_idx_parent_assert_dwarf5 -name \*.cpp.o) | awk '{s+=$5} END {printf "%\047d\n", s}'
11,436,446,616
```
That is, an increase of 0.62% in total object file size.
Looking only at debug_names:
```
$stage1_build/bin/llvm-objdump --section-headers $(find build_stage2_Debug_idx_parent_assert_dwarf5 -name \*.cpp.o) | grep __debug_names | awk '{s+="0x"$3} END {printf "%\047d\n", s}'
440,772,348
$stage1_build/bin/llvm-objdump --section-headers $(find build_stage2_Debug_no_idx_parent_assert_dwarf5 -name \*.cpp.o) | grep __debug_names | awk '{s+="0x"$3} END {printf "%\047d\n", s}'
369,867,920
```
That is an increase of 19%.
DWARF Linkers need to be changed in order to support this. This commit
already brings support to "base" linker, but it does not attempt to
modify the parallel linker. Accelerator entries refer to the
corresponding DIE offset, and this patch also requires the parent DIE
offset -- it's not clear how the parallel linker can access this. It may
be obvious to someone familiar with it, but it would be nice to get help
from its authors.
[1]:
https://discourse.llvm.org/t/rfc-improve-dwarf-5-debug-names-type-lookup-parsing-speed/74151/
2024-01-19 09:19:09 -08:00
|
|
|
|
|
|
|
for (auto &Bucket : Contents.getBuckets())
|
|
|
|
for (auto *Hash : Bucket)
|
|
|
|
for (auto *Value : Hash->getValues<DWARF5AccelTableData *>())
|
|
|
|
IndexedOffsets.insert(Value->getDieOffsetAndUnitID());
|
|
|
|
|
2023-11-18 06:36:33 -08:00
|
|
|
populateAbbrevsMap();
|
2018-04-04 14:42:14 +00:00
|
|
|
}
|
|
|
|
|
2024-01-05 11:01:19 -03:00
|
|
|
void Dwarf5AccelTableWriter::emit() {
|
2018-04-04 14:42:14 +00:00
|
|
|
Header.emit(*this);
|
|
|
|
emitCUList();
|
2023-11-18 06:36:33 -08:00
|
|
|
emitTUList();
|
2018-04-04 14:42:14 +00:00
|
|
|
emitBuckets();
|
|
|
|
emitHashes();
|
|
|
|
emitStringOffsets();
|
|
|
|
emitOffsets(EntryPool);
|
|
|
|
emitAbbrevs();
|
|
|
|
emitData();
|
2022-11-24 15:23:06 +00:00
|
|
|
Asm->OutStreamer->emitValueToAlignment(Align(4), 0);
|
2020-02-14 19:21:58 -08:00
|
|
|
Asm->OutStreamer->emitLabel(ContributionEnd);
|
2018-04-04 14:42:14 +00:00
|
|
|
}
|
|
|
|
|
[CodeGen] Refactor AppleAccelTable
Summary:
This commit separates the abstract accelerator table data structure
from the code for writing out an on-disk representation of a specific
accelerator table format. The idea is that former (now called
AccelTable<T>) can be reused for the DWARF v5 accelerator tables
as-is, without any further customizations.
Some bits of the emission code (now living in the EmissionContext class)
can be reused for DWARF v5 as well, but the subtle differences in the
layout of various subtables mean the sharing is not always possible.
(Also, the individual emit*** functions are fairly simple so there's a
tradeoff between making a bigger general-purpose function, and two
smaller targeted functions.)
Another advantage of this setup is that more of the serialization logic
can be hidden in the .cpp file -- I have moved declarations of the
header and all the emission functions there.
Reviewers: JDevlieghere, aprantl, probinson, dblaikie
Subscribers: echristo, clayborg, vleschuk, llvm-commits
Differential Revision: https://reviews.llvm.org/D43285
llvm-svn: 325516
2018-02-19 16:12:20 +00:00
|
|
|
void llvm::emitAppleAccelTableImpl(AsmPrinter *Asm, AccelTableBase &Contents,
|
|
|
|
StringRef Prefix, const MCSymbol *SecBegin,
|
|
|
|
ArrayRef<AppleAccelTableData::Atom> Atoms) {
|
|
|
|
Contents.finalize(Asm, Prefix);
|
2018-07-09 08:47:38 +00:00
|
|
|
AppleAccelTableWriter(Asm, Contents, Atoms, SecBegin).emit();
|
2018-01-29 14:52:34 +00:00
|
|
|
}
|
|
|
|
|
2023-10-05 14:47:04 -04:00
|
|
|
void llvm::emitDWARF5AccelTable(
|
2023-10-25 12:39:28 -07:00
|
|
|
AsmPrinter *Asm, DWARF5AccelTable &Contents, const DwarfDebug &DD,
|
|
|
|
ArrayRef<std::unique_ptr<DwarfCompileUnit>> CUs) {
|
2023-11-18 06:36:33 -08:00
|
|
|
TUVectorTy TUSymbols = Contents.getTypeUnitsSymbols();
|
2023-07-04 13:24:50 +02:00
|
|
|
std::vector<std::variant<MCSymbol *, uint64_t>> CompUnits;
|
2023-11-18 06:36:33 -08:00
|
|
|
std::vector<std::variant<MCSymbol *, uint64_t>> TypeUnits;
|
2018-08-24 20:31:05 +00:00
|
|
|
SmallVector<unsigned, 1> CUIndex(CUs.size());
|
2023-11-18 06:36:33 -08:00
|
|
|
DenseMap<unsigned, unsigned> TUIndex(TUSymbols.size());
|
|
|
|
int CUCount = 0;
|
|
|
|
int TUCount = 0;
|
2018-07-16 10:52:27 +00:00
|
|
|
for (const auto &CU : enumerate(CUs)) {
|
2023-06-14 13:00:38 -07:00
|
|
|
switch (CU.value()->getCUNode()->getNameTableKind()) {
|
|
|
|
case DICompileUnit::DebugNameTableKind::Default:
|
|
|
|
case DICompileUnit::DebugNameTableKind::Apple:
|
|
|
|
break;
|
|
|
|
default:
|
2018-08-16 21:29:55 +00:00
|
|
|
continue;
|
2023-06-14 13:00:38 -07:00
|
|
|
}
|
2023-11-18 06:36:33 -08:00
|
|
|
CUIndex[CU.index()] = CUCount++;
|
2018-07-16 10:52:27 +00:00
|
|
|
assert(CU.index() == CU.value()->getUniqueID());
|
|
|
|
const DwarfCompileUnit *MainCU =
|
|
|
|
DD.useSplitDwarf() ? CU.value()->getSkeleton() : CU.value().get();
|
|
|
|
CompUnits.push_back(MainCU->getLabelBegin());
|
|
|
|
}
|
|
|
|
|
2023-11-18 06:36:33 -08:00
|
|
|
for (const auto &TU : TUSymbols) {
|
|
|
|
TUIndex[TU.UniqueID] = TUCount++;
|
2023-12-04 13:56:21 -08:00
|
|
|
if (DD.useSplitDwarf())
|
|
|
|
TypeUnits.push_back(std::get<uint64_t>(TU.LabelOrSignature));
|
|
|
|
else
|
|
|
|
TypeUnits.push_back(std::get<MCSymbol *>(TU.LabelOrSignature));
|
2023-11-18 06:36:33 -08:00
|
|
|
}
|
|
|
|
|
2018-08-16 21:29:55 +00:00
|
|
|
if (CompUnits.empty())
|
|
|
|
return;
|
|
|
|
|
2022-06-10 22:50:55 -07:00
|
|
|
Asm->OutStreamer->switchSection(
|
2018-08-16 21:29:55 +00:00
|
|
|
Asm->getObjFileLowering().getDwarfDebugNamesSection());
|
|
|
|
|
2018-04-04 14:42:14 +00:00
|
|
|
Contents.finalize(Asm, "names");
|
2023-11-18 06:36:33 -08:00
|
|
|
dwarf::Form CUIndexForm =
|
|
|
|
DIEInteger::BestForm(/*IsSigned*/ false, CompUnits.size() - 1);
|
|
|
|
dwarf::Form TUIndexForm =
|
|
|
|
DIEInteger::BestForm(/*IsSigned*/ false, TypeUnits.size() - 1);
|
2024-01-05 11:01:19 -03:00
|
|
|
Dwarf5AccelTableWriter(
|
2023-11-18 06:36:33 -08:00
|
|
|
Asm, Contents, CompUnits, TypeUnits,
|
|
|
|
[&](const DWARF5AccelTableData &Entry)
|
|
|
|
-> std::optional<DWARF5AccelTable::UnitIndexAndEncoding> {
|
|
|
|
if (Entry.isTU())
|
|
|
|
return {{TUIndex[Entry.getUnitID()],
|
|
|
|
{dwarf::DW_IDX_type_unit, TUIndexForm}}};
|
|
|
|
if (CUIndex.size() > 1)
|
|
|
|
return {{CUIndex[Entry.getUnitID()],
|
|
|
|
{dwarf::DW_IDX_compile_unit, CUIndexForm}}};
|
|
|
|
return std::nullopt;
|
2023-12-04 13:56:21 -08:00
|
|
|
},
|
|
|
|
DD.useSplitDwarf())
|
2018-07-16 10:52:27 +00:00
|
|
|
.emit();
|
|
|
|
}
|
|
|
|
|
2023-11-18 06:36:33 -08:00
|
|
|
void DWARF5AccelTable::addTypeUnitSymbol(DwarfTypeUnit &U) {
|
2023-12-04 13:56:21 -08:00
|
|
|
TUSymbolsOrHashes.push_back({U.getLabelBegin(), U.getUniqueID()});
|
|
|
|
}
|
|
|
|
|
|
|
|
void DWARF5AccelTable::addTypeUnitSignature(DwarfTypeUnit &U) {
|
|
|
|
TUSymbolsOrHashes.push_back({U.getTypeSignature(), U.getUniqueID()});
|
2023-11-18 06:36:33 -08:00
|
|
|
}
|
|
|
|
|
2018-07-16 10:52:27 +00:00
|
|
|
void llvm::emitDWARF5AccelTable(
|
2023-10-25 12:39:28 -07:00
|
|
|
AsmPrinter *Asm, DWARF5AccelTable &Contents,
|
2023-07-04 13:24:50 +02:00
|
|
|
ArrayRef<std::variant<MCSymbol *, uint64_t>> CUs,
|
2023-11-18 06:36:33 -08:00
|
|
|
llvm::function_ref<std::optional<DWARF5AccelTable::UnitIndexAndEncoding>(
|
|
|
|
const DWARF5AccelTableData &)>
|
|
|
|
getIndexForEntry) {
|
|
|
|
std::vector<std::variant<MCSymbol *, uint64_t>> TypeUnits;
|
2018-07-16 10:52:27 +00:00
|
|
|
Contents.finalize(Asm, "names");
|
2024-01-05 11:01:19 -03:00
|
|
|
Dwarf5AccelTableWriter(Asm, Contents, CUs, TypeUnits, getIndexForEntry, false)
|
2018-07-16 10:52:27 +00:00
|
|
|
.emit();
|
2018-04-04 14:42:14 +00:00
|
|
|
}
|
|
|
|
|
2018-01-29 14:52:34 +00:00
|
|
|
void AppleAccelTableOffsetData::emit(AsmPrinter *Asm) const {
|
2020-09-15 11:32:08 +07:00
|
|
|
assert(Die.getDebugSectionOffset() <= UINT32_MAX &&
|
|
|
|
"The section offset exceeds the limit.");
|
2018-07-20 15:24:13 +00:00
|
|
|
Asm->emitInt32(Die.getDebugSectionOffset());
|
2018-01-29 14:52:34 +00:00
|
|
|
}
|
2011-11-07 09:18:42 +00:00
|
|
|
|
2018-01-29 14:52:34 +00:00
|
|
|
void AppleAccelTableTypeData::emit(AsmPrinter *Asm) const {
|
2020-09-15 11:32:08 +07:00
|
|
|
assert(Die.getDebugSectionOffset() <= UINT32_MAX &&
|
|
|
|
"The section offset exceeds the limit.");
|
2018-07-20 15:24:13 +00:00
|
|
|
Asm->emitInt32(Die.getDebugSectionOffset());
|
|
|
|
Asm->emitInt16(Die.getTag());
|
2018-03-29 23:32:54 +00:00
|
|
|
Asm->emitInt8(0);
|
2011-11-07 09:18:42 +00:00
|
|
|
}
|
2018-01-29 14:52:50 +00:00
|
|
|
|
|
|
|
void AppleAccelTableStaticOffsetData::emit(AsmPrinter *Asm) const {
|
2018-03-29 23:32:54 +00:00
|
|
|
Asm->emitInt32(Offset);
|
2018-01-29 14:52:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void AppleAccelTableStaticTypeData::emit(AsmPrinter *Asm) const {
|
2018-03-29 23:32:54 +00:00
|
|
|
Asm->emitInt32(Offset);
|
|
|
|
Asm->emitInt16(Tag);
|
|
|
|
Asm->emitInt8(ObjCClassIsImplementation ? dwarf::DW_FLAG_type_implementation
|
2018-01-29 14:52:50 +00:00
|
|
|
: 0);
|
2018-03-29 23:32:54 +00:00
|
|
|
Asm->emitInt32(QualifiedNameHash);
|
2018-01-29 14:52:50 +00:00
|
|
|
}
|
2018-01-29 17:28:51 +00:00
|
|
|
|
[CodeGen] Refactor AppleAccelTable
Summary:
This commit separates the abstract accelerator table data structure
from the code for writing out an on-disk representation of a specific
accelerator table format. The idea is that former (now called
AccelTable<T>) can be reused for the DWARF v5 accelerator tables
as-is, without any further customizations.
Some bits of the emission code (now living in the EmissionContext class)
can be reused for DWARF v5 as well, but the subtle differences in the
layout of various subtables mean the sharing is not always possible.
(Also, the individual emit*** functions are fairly simple so there's a
tradeoff between making a bigger general-purpose function, and two
smaller targeted functions.)
Another advantage of this setup is that more of the serialization logic
can be hidden in the .cpp file -- I have moved declarations of the
header and all the emission functions there.
Reviewers: JDevlieghere, aprantl, probinson, dblaikie
Subscribers: echristo, clayborg, vleschuk, llvm-commits
Differential Revision: https://reviews.llvm.org/D43285
llvm-svn: 325516
2018-02-19 16:12:20 +00:00
|
|
|
constexpr AppleAccelTableData::Atom AppleAccelTableTypeData::Atoms[];
|
|
|
|
constexpr AppleAccelTableData::Atom AppleAccelTableOffsetData::Atoms[];
|
|
|
|
constexpr AppleAccelTableData::Atom AppleAccelTableStaticOffsetData::Atoms[];
|
|
|
|
constexpr AppleAccelTableData::Atom AppleAccelTableStaticTypeData::Atoms[];
|
2018-01-30 13:36:30 +00:00
|
|
|
|
|
|
|
#ifndef NDEBUG
|
2018-07-09 08:47:38 +00:00
|
|
|
void AppleAccelTableWriter::Header::print(raw_ostream &OS) const {
|
2018-01-30 13:36:30 +00:00
|
|
|
OS << "Magic: " << format("0x%x", Magic) << "\n"
|
|
|
|
<< "Version: " << Version << "\n"
|
|
|
|
<< "Hash Function: " << HashFunction << "\n"
|
|
|
|
<< "Bucket Count: " << BucketCount << "\n"
|
|
|
|
<< "Header Data Length: " << HeaderDataLength << "\n";
|
|
|
|
}
|
|
|
|
|
[CodeGen] Refactor AppleAccelTable
Summary:
This commit separates the abstract accelerator table data structure
from the code for writing out an on-disk representation of a specific
accelerator table format. The idea is that former (now called
AccelTable<T>) can be reused for the DWARF v5 accelerator tables
as-is, without any further customizations.
Some bits of the emission code (now living in the EmissionContext class)
can be reused for DWARF v5 as well, but the subtle differences in the
layout of various subtables mean the sharing is not always possible.
(Also, the individual emit*** functions are fairly simple so there's a
tradeoff between making a bigger general-purpose function, and two
smaller targeted functions.)
Another advantage of this setup is that more of the serialization logic
can be hidden in the .cpp file -- I have moved declarations of the
header and all the emission functions there.
Reviewers: JDevlieghere, aprantl, probinson, dblaikie
Subscribers: echristo, clayborg, vleschuk, llvm-commits
Differential Revision: https://reviews.llvm.org/D43285
llvm-svn: 325516
2018-02-19 16:12:20 +00:00
|
|
|
void AppleAccelTableData::Atom::print(raw_ostream &OS) const {
|
2018-01-30 13:36:30 +00:00
|
|
|
OS << "Type: " << dwarf::AtomTypeString(Type) << "\n"
|
|
|
|
<< "Form: " << dwarf::FormEncodingString(Form) << "\n";
|
|
|
|
}
|
|
|
|
|
2018-07-09 08:47:38 +00:00
|
|
|
void AppleAccelTableWriter::HeaderData::print(raw_ostream &OS) const {
|
2018-01-30 13:36:30 +00:00
|
|
|
OS << "DIE Offset Base: " << DieOffsetBase << "\n";
|
|
|
|
for (auto Atom : Atoms)
|
|
|
|
Atom.print(OS);
|
|
|
|
}
|
|
|
|
|
2018-07-09 08:47:38 +00:00
|
|
|
void AppleAccelTableWriter::print(raw_ostream &OS) const {
|
2018-01-30 13:36:30 +00:00
|
|
|
Header.print(OS);
|
|
|
|
HeaderData.print(OS);
|
[CodeGen] Refactor AppleAccelTable
Summary:
This commit separates the abstract accelerator table data structure
from the code for writing out an on-disk representation of a specific
accelerator table format. The idea is that former (now called
AccelTable<T>) can be reused for the DWARF v5 accelerator tables
as-is, without any further customizations.
Some bits of the emission code (now living in the EmissionContext class)
can be reused for DWARF v5 as well, but the subtle differences in the
layout of various subtables mean the sharing is not always possible.
(Also, the individual emit*** functions are fairly simple so there's a
tradeoff between making a bigger general-purpose function, and two
smaller targeted functions.)
Another advantage of this setup is that more of the serialization logic
can be hidden in the .cpp file -- I have moved declarations of the
header and all the emission functions there.
Reviewers: JDevlieghere, aprantl, probinson, dblaikie
Subscribers: echristo, clayborg, vleschuk, llvm-commits
Differential Revision: https://reviews.llvm.org/D43285
llvm-svn: 325516
2018-02-19 16:12:20 +00:00
|
|
|
Contents.print(OS);
|
|
|
|
SecBegin->print(OS, nullptr);
|
2018-01-30 13:36:30 +00:00
|
|
|
}
|
|
|
|
|
[CodeGen] Refactor AppleAccelTable
Summary:
This commit separates the abstract accelerator table data structure
from the code for writing out an on-disk representation of a specific
accelerator table format. The idea is that former (now called
AccelTable<T>) can be reused for the DWARF v5 accelerator tables
as-is, without any further customizations.
Some bits of the emission code (now living in the EmissionContext class)
can be reused for DWARF v5 as well, but the subtle differences in the
layout of various subtables mean the sharing is not always possible.
(Also, the individual emit*** functions are fairly simple so there's a
tradeoff between making a bigger general-purpose function, and two
smaller targeted functions.)
Another advantage of this setup is that more of the serialization logic
can be hidden in the .cpp file -- I have moved declarations of the
header and all the emission functions there.
Reviewers: JDevlieghere, aprantl, probinson, dblaikie
Subscribers: echristo, clayborg, vleschuk, llvm-commits
Differential Revision: https://reviews.llvm.org/D43285
llvm-svn: 325516
2018-02-19 16:12:20 +00:00
|
|
|
void AccelTableBase::HashData::print(raw_ostream &OS) const {
|
2018-02-09 10:06:56 +00:00
|
|
|
OS << "Name: " << Name.getString() << "\n";
|
2018-01-30 13:36:30 +00:00
|
|
|
OS << " Hash Value: " << format("0x%x", HashValue) << "\n";
|
|
|
|
OS << " Symbol: ";
|
|
|
|
if (Sym)
|
|
|
|
OS << *Sym;
|
|
|
|
else
|
|
|
|
OS << "<none>";
|
|
|
|
OS << "\n";
|
2018-02-09 10:06:56 +00:00
|
|
|
for (auto *Value : Values)
|
2018-01-30 13:36:30 +00:00
|
|
|
Value->print(OS);
|
|
|
|
}
|
|
|
|
|
[CodeGen] Refactor AppleAccelTable
Summary:
This commit separates the abstract accelerator table data structure
from the code for writing out an on-disk representation of a specific
accelerator table format. The idea is that former (now called
AccelTable<T>) can be reused for the DWARF v5 accelerator tables
as-is, without any further customizations.
Some bits of the emission code (now living in the EmissionContext class)
can be reused for DWARF v5 as well, but the subtle differences in the
layout of various subtables mean the sharing is not always possible.
(Also, the individual emit*** functions are fairly simple so there's a
tradeoff between making a bigger general-purpose function, and two
smaller targeted functions.)
Another advantage of this setup is that more of the serialization logic
can be hidden in the .cpp file -- I have moved declarations of the
header and all the emission functions there.
Reviewers: JDevlieghere, aprantl, probinson, dblaikie
Subscribers: echristo, clayborg, vleschuk, llvm-commits
Differential Revision: https://reviews.llvm.org/D43285
llvm-svn: 325516
2018-02-19 16:12:20 +00:00
|
|
|
void AccelTableBase::print(raw_ostream &OS) const {
|
2018-01-30 13:36:30 +00:00
|
|
|
// Print Content.
|
|
|
|
OS << "Entries: \n";
|
2023-07-19 19:50:36 -07:00
|
|
|
for (const auto &[Name, Data] : Entries) {
|
|
|
|
OS << "Name: " << Name << "\n";
|
|
|
|
for (auto *V : Data.Values)
|
2018-01-30 13:36:30 +00:00
|
|
|
V->print(OS);
|
|
|
|
}
|
|
|
|
|
|
|
|
OS << "Buckets and Hashes: \n";
|
2022-07-17 01:33:28 -07:00
|
|
|
for (const auto &Bucket : Buckets)
|
|
|
|
for (const auto &Hash : Bucket)
|
2018-01-30 13:36:30 +00:00
|
|
|
Hash->print(OS);
|
|
|
|
|
|
|
|
OS << "Data: \n";
|
2022-07-17 01:33:28 -07:00
|
|
|
for (const auto &E : Entries)
|
2018-02-09 10:06:56 +00:00
|
|
|
E.second.print(OS);
|
2018-01-30 13:36:30 +00:00
|
|
|
}
|
|
|
|
|
2018-04-04 14:42:14 +00:00
|
|
|
void DWARF5AccelTableData::print(raw_ostream &OS) const {
|
2018-07-16 10:52:27 +00:00
|
|
|
OS << " Offset: " << getDieOffset() << "\n";
|
|
|
|
OS << " Tag: " << dwarf::TagString(getDieTag()) << "\n";
|
|
|
|
}
|
|
|
|
|
2018-01-30 13:36:30 +00:00
|
|
|
void AppleAccelTableOffsetData::print(raw_ostream &OS) const {
|
2018-07-20 15:40:24 +00:00
|
|
|
OS << " Offset: " << Die.getOffset() << "\n";
|
2018-01-30 13:36:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void AppleAccelTableTypeData::print(raw_ostream &OS) const {
|
2018-07-20 15:40:24 +00:00
|
|
|
OS << " Offset: " << Die.getOffset() << "\n";
|
|
|
|
OS << " Tag: " << dwarf::TagString(Die.getTag()) << "\n";
|
2018-01-30 13:36:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void AppleAccelTableStaticOffsetData::print(raw_ostream &OS) const {
|
|
|
|
OS << " Static Offset: " << Offset << "\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
void AppleAccelTableStaticTypeData::print(raw_ostream &OS) const {
|
|
|
|
OS << " Static Offset: " << Offset << "\n";
|
|
|
|
OS << " QualifiedNameHash: " << format("%x\n", QualifiedNameHash) << "\n";
|
|
|
|
OS << " Tag: " << dwarf::TagString(Tag) << "\n";
|
|
|
|
OS << " ObjCClassIsImplementation: "
|
|
|
|
<< (ObjCClassIsImplementation ? "true" : "false");
|
|
|
|
OS << "\n";
|
|
|
|
}
|
|
|
|
#endif
|