summaryrefslogtreecommitdiff
path: root/lib/CodeGen/AsmPrinter
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2018-07-28 10:51:19 +0000
committerDimitry Andric <dim@FreeBSD.org>2018-07-28 10:51:19 +0000
commiteb11fae6d08f479c0799db45860a98af528fa6e7 (patch)
tree44d492a50c8c1a7eb8e2d17ea3360ec4d066f042 /lib/CodeGen/AsmPrinter
parentb8a2042aa938069e862750553db0e4d82d25822c (diff)
Notes
Diffstat (limited to 'lib/CodeGen/AsmPrinter')
-rw-r--r--lib/CodeGen/AsmPrinter/ARMException.cpp5
-rw-r--r--lib/CodeGen/AsmPrinter/AccelTable.cpp721
-rw-r--r--lib/CodeGen/AsmPrinter/AddressPool.cpp2
-rw-r--r--lib/CodeGen/AsmPrinter/AddressPool.h2
-rw-r--r--lib/CodeGen/AsmPrinter/AsmPrinter.cpp234
-rw-r--r--lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp34
-rw-r--r--lib/CodeGen/AsmPrinter/AsmPrinterHandler.h18
-rw-r--r--lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp3
-rw-r--r--lib/CodeGen/AsmPrinter/ByteStreamer.h24
-rw-r--r--lib/CodeGen/AsmPrinter/CMakeLists.txt3
-rw-r--r--lib/CodeGen/AsmPrinter/CodeViewDebug.cpp477
-rw-r--r--lib/CodeGen/AsmPrinter/CodeViewDebug.h76
-rw-r--r--lib/CodeGen/AsmPrinter/DIE.cpp132
-rw-r--r--lib/CodeGen/AsmPrinter/DIEHash.cpp24
-rw-r--r--lib/CodeGen/AsmPrinter/DIEHash.h38
-rw-r--r--lib/CodeGen/AsmPrinter/DbgValueHistoryCalculator.cpp54
-rw-r--r--lib/CodeGen/AsmPrinter/DbgValueHistoryCalculator.h4
-rw-r--r--lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp33
-rw-r--r--lib/CodeGen/AsmPrinter/DebugHandlerBase.h8
-rw-r--r--lib/CodeGen/AsmPrinter/DebugLocEntry.h17
-rw-r--r--lib/CodeGen/AsmPrinter/DebugLocStream.h8
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfAccelTable.cpp293
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfAccelTable.h261
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfCFIException.cpp2
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp189
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfCompileUnit.h31
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfDebug.cpp665
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfDebug.h121
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfException.h2
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfExpression.cpp29
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfExpression.h3
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfFile.cpp44
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfFile.h54
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfStringPool.cpp29
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfStringPool.h9
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfUnit.cpp234
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfUnit.h40
-rw-r--r--lib/CodeGen/AsmPrinter/EHStreamer.cpp152
-rw-r--r--lib/CodeGen/AsmPrinter/EHStreamer.h12
-rw-r--r--lib/CodeGen/AsmPrinter/ErlangGCPrinter.cpp12
-rw-r--r--lib/CodeGen/AsmPrinter/OcamlGCPrinter.cpp10
-rw-r--r--lib/CodeGen/AsmPrinter/WinCFGuard.cpp45
-rw-r--r--lib/CodeGen/AsmPrinter/WinCFGuard.h54
-rw-r--r--lib/CodeGen/AsmPrinter/WinException.cpp2
-rw-r--r--lib/CodeGen/AsmPrinter/WinException.h2
45 files changed, 2821 insertions, 1391 deletions
diff --git a/lib/CodeGen/AsmPrinter/ARMException.cpp b/lib/CodeGen/AsmPrinter/ARMException.cpp
index 15cfbd5c40ff..9011f025f595 100644
--- a/lib/CodeGen/AsmPrinter/ARMException.cpp
+++ b/lib/CodeGen/AsmPrinter/ARMException.cpp
@@ -91,7 +91,8 @@ void ARMException::endFunction(const MachineFunction *MF) {
ATS.emitFnEnd();
}
-void ARMException::emitTypeInfos(unsigned TTypeEncoding) {
+void ARMException::emitTypeInfos(unsigned TTypeEncoding,
+ MCSymbol *TTBaseLabel) {
const MachineFunction *MF = Asm->MF;
const std::vector<const GlobalValue *> &TypeInfos = MF->getTypeInfos();
const std::vector<unsigned> &FilterIds = MF->getFilterIds();
@@ -112,6 +113,8 @@ void ARMException::emitTypeInfos(unsigned TTypeEncoding) {
Asm->EmitTTypeReference(GV, TTypeEncoding);
}
+ Asm->OutStreamer->EmitLabel(TTBaseLabel);
+
// Emit the Exception Specifications.
if (VerboseAsm && !FilterIds.empty()) {
Asm->OutStreamer->AddComment(">> Filter TypeInfos <<");
diff --git a/lib/CodeGen/AsmPrinter/AccelTable.cpp b/lib/CodeGen/AsmPrinter/AccelTable.cpp
new file mode 100644
index 000000000000..20b0b8d3feab
--- /dev/null
+++ b/lib/CodeGen/AsmPrinter/AccelTable.cpp
@@ -0,0 +1,721 @@
+//===- llvm/CodeGen/AsmPrinter/AccelTable.cpp - Accelerator Tables --------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains support for writing accelerator tables.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/CodeGen/AccelTable.h"
+#include "DwarfCompileUnit.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/BinaryFormat/Dwarf.h"
+#include "llvm/CodeGen/AsmPrinter.h"
+#include "llvm/CodeGen/DIE.h"
+#include "llvm/MC/MCExpr.h"
+#include "llvm/MC/MCStreamer.h"
+#include "llvm/MC/MCSymbol.h"
+#include "llvm/Support/raw_ostream.h"
+#include <algorithm>
+#include <cstddef>
+#include <cstdint>
+#include <limits>
+#include <vector>
+
+using namespace llvm;
+
+void AccelTableBase::computeBucketCount() {
+ // First get the number of unique hashes.
+ std::vector<uint32_t> Uniques;
+ Uniques.reserve(Entries.size());
+ for (const auto &E : Entries)
+ Uniques.push_back(E.second.HashValue);
+ array_pod_sort(Uniques.begin(), Uniques.end());
+ std::vector<uint32_t>::iterator P =
+ std::unique(Uniques.begin(), Uniques.end());
+
+ UniqueHashCount = std::distance(Uniques.begin(), P);
+
+ if (UniqueHashCount > 1024)
+ BucketCount = UniqueHashCount / 4;
+ else if (UniqueHashCount > 16)
+ BucketCount = UniqueHashCount / 2;
+ else
+ BucketCount = std::max<uint32_t>(UniqueHashCount, 1);
+}
+
+void AccelTableBase::finalize(AsmPrinter *Asm, StringRef Prefix) {
+ // Create the individual hash data outputs.
+ for (auto &E : Entries) {
+ // Unique the entries.
+ std::stable_sort(E.second.Values.begin(), E.second.Values.end(),
+ [](const AccelTableData *A, const AccelTableData *B) {
+ return *A < *B;
+ });
+ 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)
+ std::stable_sort(Bucket.begin(), Bucket.end(),
+ [](HashData *LHS, HashData *RHS) {
+ return LHS->HashValue < RHS->HashValue;
+ });
+}
+
+namespace {
+/// Base class for writing out Accelerator tables. It holds the common
+/// functionality for the two Accelerator table types.
+class AccelTableWriter {
+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:
+ AccelTableWriter(AsmPrinter *Asm, const AccelTableBase &Contents,
+ bool SkipIdenticalHashes)
+ : Asm(Asm), Contents(Contents), SkipIdenticalHashes(SkipIdenticalHashes) {
+ }
+};
+
+class AppleAccelTableWriter : public AccelTableWriter {
+ 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:
+ AppleAccelTableWriter(AsmPrinter *Asm, const AccelTableBase &Contents,
+ ArrayRef<Atom> Atoms, const MCSymbol *SecBegin)
+ : AccelTableWriter(Asm, Contents, true),
+ 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
+};
+
+/// Class responsible for emitting a DWARF v5 Accelerator Table. The only
+/// public function is emit(), which performs the actual emission.
+///
+/// The class is templated in its data type. This allows us to emit both dyamic
+/// and static data entries. A callback abstract the logic to provide a CU
+/// index for a given entry, which is different per data type, but identical
+/// for every entry in the same table.
+template <typename DataT>
+class Dwarf5AccelTableWriter : public AccelTableWriter {
+ struct Header {
+ uint32_t UnitLength = 0;
+ uint16_t Version = 5;
+ uint16_t Padding = 0;
+ uint32_t CompUnitCount;
+ uint32_t LocalTypeUnitCount = 0;
+ uint32_t ForeignTypeUnitCount = 0;
+ uint32_t BucketCount;
+ uint32_t NameCount;
+ uint32_t AbbrevTableSize = 0;
+ uint32_t AugmentationStringSize = sizeof(AugmentationString);
+ char AugmentationString[8] = {'L', 'L', 'V', 'M', '0', '7', '0', '0'};
+
+ Header(uint32_t CompUnitCount, uint32_t BucketCount, uint32_t NameCount)
+ : CompUnitCount(CompUnitCount), BucketCount(BucketCount),
+ NameCount(NameCount) {}
+
+ void emit(const Dwarf5AccelTableWriter &Ctx) const;
+ };
+ struct AttributeEncoding {
+ dwarf::Index Index;
+ dwarf::Form Form;
+ };
+
+ Header Header;
+ DenseMap<uint32_t, SmallVector<AttributeEncoding, 2>> Abbreviations;
+ ArrayRef<MCSymbol *> CompUnits;
+ llvm::function_ref<unsigned(const DataT &)> getCUIndexForEntry;
+ MCSymbol *ContributionStart = Asm->createTempSymbol("names_start");
+ MCSymbol *ContributionEnd = Asm->createTempSymbol("names_end");
+ MCSymbol *AbbrevStart = Asm->createTempSymbol("names_abbrev_start");
+ MCSymbol *AbbrevEnd = Asm->createTempSymbol("names_abbrev_end");
+ MCSymbol *EntryPool = Asm->createTempSymbol("names_entries");
+
+ DenseSet<uint32_t> getUniqueTags() const;
+
+ // Right now, we emit uniform attributes for all tags.
+ SmallVector<AttributeEncoding, 2> getUniformAttributes() const;
+
+ void emitCUList() const;
+ void emitBuckets() const;
+ void emitStringOffsets() const;
+ void emitAbbrevs() const;
+ void emitEntry(const DataT &Entry) const;
+ void emitData() const;
+
+public:
+ Dwarf5AccelTableWriter(
+ AsmPrinter *Asm, const AccelTableBase &Contents,
+ ArrayRef<MCSymbol *> CompUnits,
+ llvm::function_ref<unsigned(const DataT &)> GetCUIndexForEntry);
+
+ void emit() const;
+};
+} // namespace
+
+void AccelTableWriter::emitHashes() const {
+ uint64_t PrevHash = std::numeric_limits<uint64_t>::max();
+ unsigned BucketIdx = 0;
+ for (auto &Bucket : Contents.getBuckets()) {
+ for (auto &Hash : Bucket) {
+ uint32_t HashValue = Hash->HashValue;
+ if (SkipIdenticalHashes && PrevHash == HashValue)
+ continue;
+ Asm->OutStreamer->AddComment("Hash in Bucket " + Twine(BucketIdx));
+ Asm->emitInt32(HashValue);
+ PrevHash = HashValue;
+ }
+ BucketIdx++;
+ }
+}
+
+void AccelTableWriter::emitOffsets(const MCSymbol *Base) const {
+ 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));
+ Asm->EmitLabelDifference(Hash->Sym, Base, sizeof(uint32_t));
+ }
+ }
+}
+
+void AppleAccelTableWriter::Header::emit(AsmPrinter *Asm) const {
+ Asm->OutStreamer->AddComment("Header Magic");
+ Asm->emitInt32(Magic);
+ Asm->OutStreamer->AddComment("Header Version");
+ Asm->emitInt16(Version);
+ Asm->OutStreamer->AddComment("Header Hash Function");
+ Asm->emitInt16(HashFunction);
+ Asm->OutStreamer->AddComment("Header Bucket Count");
+ Asm->emitInt32(BucketCount);
+ Asm->OutStreamer->AddComment("Header Hash Count");
+ Asm->emitInt32(HashCount);
+ Asm->OutStreamer->AddComment("Header Data Length");
+ Asm->emitInt32(HeaderDataLength);
+}
+
+void AppleAccelTableWriter::HeaderData::emit(AsmPrinter *Asm) const {
+ Asm->OutStreamer->AddComment("HeaderData Die Offset Base");
+ Asm->emitInt32(DieOffsetBase);
+ Asm->OutStreamer->AddComment("HeaderData Atom Count");
+ Asm->emitInt32(Atoms.size());
+
+ for (const Atom &A : Atoms) {
+ Asm->OutStreamer->AddComment(dwarf::AtomTypeString(A.Type));
+ Asm->emitInt16(A.Type);
+ Asm->OutStreamer->AddComment(dwarf::FormEncodingString(A.Form));
+ Asm->emitInt16(A.Form);
+ }
+}
+
+void AppleAccelTableWriter::emitBuckets() const {
+ const auto &Buckets = Contents.getBuckets();
+ unsigned index = 0;
+ for (size_t i = 0, e = Buckets.size(); i < e; ++i) {
+ Asm->OutStreamer->AddComment("Bucket " + Twine(i));
+ if (!Buckets[i].empty())
+ Asm->emitInt32(index);
+ else
+ Asm->emitInt32(std::numeric_limits<uint32_t>::max());
+ // Buckets point in the list of hashes, not to the data. Do not increment
+ // the index multiple times in case of hash collisions.
+ uint64_t PrevHash = std::numeric_limits<uint64_t>::max();
+ for (auto *HD : Buckets[i]) {
+ uint32_t HashValue = HD->HashValue;
+ if (PrevHash != HashValue)
+ ++index;
+ PrevHash = HashValue;
+ }
+ }
+}
+
+void AppleAccelTableWriter::emitData() const {
+ const auto &Buckets = Contents.getBuckets();
+ for (size_t i = 0, e = Buckets.size(); i < e; ++i) {
+ uint64_t PrevHash = std::numeric_limits<uint64_t>::max();
+ for (auto &Hash : Buckets[i]) {
+ // Terminate the previous entry if there is no hash collision with the
+ // current one.
+ if (PrevHash != std::numeric_limits<uint64_t>::max() &&
+ PrevHash != Hash->HashValue)
+ Asm->emitInt32(0);
+ // Remember to emit the label for our offset.
+ Asm->OutStreamer->EmitLabel(Hash->Sym);
+ Asm->OutStreamer->AddComment(Hash->Name.getString());
+ Asm->emitDwarfStringOffset(Hash->Name);
+ Asm->OutStreamer->AddComment("Num DIEs");
+ Asm->emitInt32(Hash->Values.size());
+ for (const auto *V : Hash->Values)
+ static_cast<const AppleAccelTableData *>(V)->emit(Asm);
+ PrevHash = Hash->HashValue;
+ }
+ // Emit the final end marker for the bucket.
+ if (!Buckets[i].empty())
+ Asm->emitInt32(0);
+ }
+}
+
+void AppleAccelTableWriter::emit() const {
+ Header.emit(Asm);
+ HeaderData.emit(Asm);
+ emitBuckets();
+ emitHashes();
+ emitOffsets(SecBegin);
+ emitData();
+}
+
+template <typename DataT>
+void Dwarf5AccelTableWriter<DataT>::Header::emit(
+ const Dwarf5AccelTableWriter &Ctx) const {
+ assert(CompUnitCount > 0 && "Index must have at least one CU.");
+
+ AsmPrinter *Asm = Ctx.Asm;
+ Asm->OutStreamer->AddComment("Header: unit length");
+ Asm->EmitLabelDifference(Ctx.ContributionEnd, Ctx.ContributionStart,
+ sizeof(uint32_t));
+ Asm->OutStreamer->EmitLabel(Ctx.ContributionStart);
+ 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");
+ Asm->EmitLabelDifference(Ctx.AbbrevEnd, Ctx.AbbrevStart, sizeof(uint32_t));
+ Asm->OutStreamer->AddComment("Header: augmentation string size");
+ assert(AugmentationStringSize % 4 == 0);
+ Asm->emitInt32(AugmentationStringSize);
+ Asm->OutStreamer->AddComment("Header: augmentation string");
+ Asm->OutStreamer->EmitBytes({AugmentationString, AugmentationStringSize});
+}
+
+template <typename DataT>
+DenseSet<uint32_t> Dwarf5AccelTableWriter<DataT>::getUniqueTags() const {
+ DenseSet<uint32_t> UniqueTags;
+ for (auto &Bucket : Contents.getBuckets()) {
+ for (auto *Hash : Bucket) {
+ for (auto *Value : Hash->Values) {
+ unsigned Tag = static_cast<const DataT *>(Value)->getDieTag();
+ UniqueTags.insert(Tag);
+ }
+ }
+ }
+ return UniqueTags;
+}
+
+template <typename DataT>
+SmallVector<typename Dwarf5AccelTableWriter<DataT>::AttributeEncoding, 2>
+Dwarf5AccelTableWriter<DataT>::getUniformAttributes() const {
+ SmallVector<AttributeEncoding, 2> UA;
+ if (CompUnits.size() > 1) {
+ size_t LargestCUIndex = CompUnits.size() - 1;
+ dwarf::Form Form = DIEInteger::BestForm(/*IsSigned*/ false, LargestCUIndex);
+ UA.push_back({dwarf::DW_IDX_compile_unit, Form});
+ }
+ UA.push_back({dwarf::DW_IDX_die_offset, dwarf::DW_FORM_ref4});
+ return UA;
+}
+
+template <typename DataT>
+void Dwarf5AccelTableWriter<DataT>::emitCUList() const {
+ for (const auto &CU : enumerate(CompUnits)) {
+ Asm->OutStreamer->AddComment("Compilation unit " + Twine(CU.index()));
+ Asm->emitDwarfSymbolReference(CU.value());
+ }
+}
+
+template <typename DataT>
+void Dwarf5AccelTableWriter<DataT>::emitBuckets() const {
+ 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();
+ }
+}
+
+template <typename DataT>
+void Dwarf5AccelTableWriter<DataT>::emitStringOffsets() const {
+ 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);
+ }
+ }
+}
+
+template <typename DataT>
+void Dwarf5AccelTableWriter<DataT>::emitAbbrevs() const {
+ Asm->OutStreamer->EmitLabel(AbbrevStart);
+ for (const auto &Abbrev : Abbreviations) {
+ Asm->OutStreamer->AddComment("Abbrev code");
+ assert(Abbrev.first != 0);
+ Asm->EmitULEB128(Abbrev.first);
+ Asm->OutStreamer->AddComment(dwarf::TagString(Abbrev.first));
+ Asm->EmitULEB128(Abbrev.first);
+ for (const auto &AttrEnc : Abbrev.second) {
+ Asm->EmitULEB128(AttrEnc.Index, dwarf::IndexString(AttrEnc.Index).data());
+ Asm->EmitULEB128(AttrEnc.Form,
+ dwarf::FormEncodingString(AttrEnc.Form).data());
+ }
+ Asm->EmitULEB128(0, "End of abbrev");
+ Asm->EmitULEB128(0, "End of abbrev");
+ }
+ Asm->EmitULEB128(0, "End of abbrev list");
+ Asm->OutStreamer->EmitLabel(AbbrevEnd);
+}
+
+template <typename DataT>
+void Dwarf5AccelTableWriter<DataT>::emitEntry(const DataT &Entry) const {
+ auto AbbrevIt = Abbreviations.find(Entry.getDieTag());
+ assert(AbbrevIt != Abbreviations.end() &&
+ "Why wasn't this abbrev generated?");
+
+ Asm->EmitULEB128(AbbrevIt->first, "Abbreviation code");
+ for (const auto &AttrEnc : AbbrevIt->second) {
+ Asm->OutStreamer->AddComment(dwarf::IndexString(AttrEnc.Index));
+ switch (AttrEnc.Index) {
+ case dwarf::DW_IDX_compile_unit: {
+ DIEInteger ID(getCUIndexForEntry(Entry));
+ ID.EmitValue(Asm, AttrEnc.Form);
+ break;
+ }
+ case dwarf::DW_IDX_die_offset:
+ assert(AttrEnc.Form == dwarf::DW_FORM_ref4);
+ Asm->emitInt32(Entry.getDieOffset());
+ break;
+ default:
+ llvm_unreachable("Unexpected index attribute!");
+ }
+ }
+}
+
+template <typename DataT> void Dwarf5AccelTableWriter<DataT>::emitData() const {
+ Asm->OutStreamer->EmitLabel(EntryPool);
+ for (auto &Bucket : Contents.getBuckets()) {
+ for (auto *Hash : Bucket) {
+ // Remember to emit the label for our offset.
+ Asm->OutStreamer->EmitLabel(Hash->Sym);
+ for (const auto *Value : Hash->Values)
+ emitEntry(*static_cast<const DataT *>(Value));
+ Asm->OutStreamer->AddComment("End of list: " + Hash->Name.getString());
+ Asm->emitInt32(0);
+ }
+ }
+}
+
+template <typename DataT>
+Dwarf5AccelTableWriter<DataT>::Dwarf5AccelTableWriter(
+ AsmPrinter *Asm, const AccelTableBase &Contents,
+ ArrayRef<MCSymbol *> CompUnits,
+ llvm::function_ref<unsigned(const DataT &)> getCUIndexForEntry)
+ : AccelTableWriter(Asm, Contents, false),
+ Header(CompUnits.size(), Contents.getBucketCount(),
+ Contents.getUniqueNameCount()),
+ CompUnits(CompUnits), getCUIndexForEntry(std::move(getCUIndexForEntry)) {
+ DenseSet<uint32_t> UniqueTags = getUniqueTags();
+ SmallVector<AttributeEncoding, 2> UniformAttributes = getUniformAttributes();
+
+ Abbreviations.reserve(UniqueTags.size());
+ for (uint32_t Tag : UniqueTags)
+ Abbreviations.try_emplace(Tag, UniformAttributes);
+}
+
+template <typename DataT> void Dwarf5AccelTableWriter<DataT>::emit() const {
+ Header.emit(*this);
+ emitCUList();
+ emitBuckets();
+ emitHashes();
+ emitStringOffsets();
+ emitOffsets(EntryPool);
+ emitAbbrevs();
+ emitData();
+ Asm->OutStreamer->EmitValueToAlignment(4, 0);
+ Asm->OutStreamer->EmitLabel(ContributionEnd);
+}
+
+void llvm::emitAppleAccelTableImpl(AsmPrinter *Asm, AccelTableBase &Contents,
+ StringRef Prefix, const MCSymbol *SecBegin,
+ ArrayRef<AppleAccelTableData::Atom> Atoms) {
+ Contents.finalize(Asm, Prefix);
+ AppleAccelTableWriter(Asm, Contents, Atoms, SecBegin).emit();
+}
+
+void llvm::emitDWARF5AccelTable(
+ AsmPrinter *Asm, AccelTable<DWARF5AccelTableData> &Contents,
+ const DwarfDebug &DD, ArrayRef<std::unique_ptr<DwarfCompileUnit>> CUs) {
+ std::vector<MCSymbol *> CompUnits;
+ for (const auto &CU : enumerate(CUs)) {
+ assert(CU.index() == CU.value()->getUniqueID());
+ const DwarfCompileUnit *MainCU =
+ DD.useSplitDwarf() ? CU.value()->getSkeleton() : CU.value().get();
+ CompUnits.push_back(MainCU->getLabelBegin());
+ }
+
+ Contents.finalize(Asm, "names");
+ Dwarf5AccelTableWriter<DWARF5AccelTableData>(
+ Asm, Contents, CompUnits,
+ [&DD](const DWARF5AccelTableData &Entry) {
+ const DIE *CUDie = Entry.getDie().getUnitDie();
+ return DD.lookupCU(CUDie)->getUniqueID();
+ })
+ .emit();
+}
+
+void llvm::emitDWARF5AccelTable(
+ AsmPrinter *Asm, AccelTable<DWARF5AccelTableStaticData> &Contents,
+ ArrayRef<MCSymbol *> CUs,
+ llvm::function_ref<unsigned(const DWARF5AccelTableStaticData &)>
+ getCUIndexForEntry) {
+ Contents.finalize(Asm, "names");
+ Dwarf5AccelTableWriter<DWARF5AccelTableStaticData>(Asm, Contents, CUs,
+ getCUIndexForEntry)
+ .emit();
+}
+
+void AppleAccelTableOffsetData::emit(AsmPrinter *Asm) const {
+ Asm->emitInt32(Die.getDebugSectionOffset());
+}
+
+void AppleAccelTableTypeData::emit(AsmPrinter *Asm) const {
+ Asm->emitInt32(Die.getDebugSectionOffset());
+ Asm->emitInt16(Die.getTag());
+ Asm->emitInt8(0);
+}
+
+void AppleAccelTableStaticOffsetData::emit(AsmPrinter *Asm) const {
+ Asm->emitInt32(Offset);
+}
+
+void AppleAccelTableStaticTypeData::emit(AsmPrinter *Asm) const {
+ Asm->emitInt32(Offset);
+ Asm->emitInt16(Tag);
+ Asm->emitInt8(ObjCClassIsImplementation ? dwarf::DW_FLAG_type_implementation
+ : 0);
+ Asm->emitInt32(QualifiedNameHash);
+}
+
+#ifndef _MSC_VER
+// The lines below are rejected by older versions (TBD) of MSVC.
+constexpr AppleAccelTableData::Atom AppleAccelTableTypeData::Atoms[];
+constexpr AppleAccelTableData::Atom AppleAccelTableOffsetData::Atoms[];
+constexpr AppleAccelTableData::Atom AppleAccelTableStaticOffsetData::Atoms[];
+constexpr AppleAccelTableData::Atom AppleAccelTableStaticTypeData::Atoms[];
+#else
+// FIXME: Erase this path once the minimum MSCV version has been bumped.
+const SmallVector<AppleAccelTableData::Atom, 4>
+ AppleAccelTableOffsetData::Atoms = {
+ Atom(dwarf::DW_ATOM_die_offset, dwarf::DW_FORM_data4)};
+const SmallVector<AppleAccelTableData::Atom, 4> AppleAccelTableTypeData::Atoms =
+ {Atom(dwarf::DW_ATOM_die_offset, dwarf::DW_FORM_data4),
+ Atom(dwarf::DW_ATOM_die_tag, dwarf::DW_FORM_data2),
+ Atom(dwarf::DW_ATOM_type_flags, dwarf::DW_FORM_data1)};
+const SmallVector<AppleAccelTableData::Atom, 4>
+ AppleAccelTableStaticOffsetData::Atoms = {
+ Atom(dwarf::DW_ATOM_die_offset, dwarf::DW_FORM_data4)};
+const SmallVector<AppleAccelTableData::Atom, 4>
+ AppleAccelTableStaticTypeData::Atoms = {
+ Atom(dwarf::DW_ATOM_die_offset, dwarf::DW_FORM_data4),
+ Atom(dwarf::DW_ATOM_die_tag, dwarf::DW_FORM_data2),
+ Atom(5, dwarf::DW_FORM_data1), Atom(6, dwarf::DW_FORM_data4)};
+#endif
+
+#ifndef NDEBUG
+void AppleAccelTableWriter::Header::print(raw_ostream &OS) const {
+ OS << "Magic: " << format("0x%x", Magic) << "\n"
+ << "Version: " << Version << "\n"
+ << "Hash Function: " << HashFunction << "\n"
+ << "Bucket Count: " << BucketCount << "\n"
+ << "Header Data Length: " << HeaderDataLength << "\n";
+}
+
+void AppleAccelTableData::Atom::print(raw_ostream &OS) const {
+ OS << "Type: " << dwarf::AtomTypeString(Type) << "\n"
+ << "Form: " << dwarf::FormEncodingString(Form) << "\n";
+}
+
+void AppleAccelTableWriter::HeaderData::print(raw_ostream &OS) const {
+ OS << "DIE Offset Base: " << DieOffsetBase << "\n";
+ for (auto Atom : Atoms)
+ Atom.print(OS);
+}
+
+void AppleAccelTableWriter::print(raw_ostream &OS) const {
+ Header.print(OS);
+ HeaderData.print(OS);
+ Contents.print(OS);
+ SecBegin->print(OS, nullptr);
+}
+
+void AccelTableBase::HashData::print(raw_ostream &OS) const {
+ OS << "Name: " << Name.getString() << "\n";
+ OS << " Hash Value: " << format("0x%x", HashValue) << "\n";
+ OS << " Symbol: ";
+ if (Sym)
+ OS << *Sym;
+ else
+ OS << "<none>";
+ OS << "\n";
+ for (auto *Value : Values)
+ Value->print(OS);
+}
+
+void AccelTableBase::print(raw_ostream &OS) const {
+ // Print Content.
+ OS << "Entries: \n";
+ for (const auto &Entry : Entries) {
+ OS << "Name: " << Entry.first() << "\n";
+ for (auto *V : Entry.second.Values)
+ V->print(OS);
+ }
+
+ OS << "Buckets and Hashes: \n";
+ for (auto &Bucket : Buckets)
+ for (auto &Hash : Bucket)
+ Hash->print(OS);
+
+ OS << "Data: \n";
+ for (auto &E : Entries)
+ E.second.print(OS);
+}
+
+void DWARF5AccelTableData::print(raw_ostream &OS) const {
+ OS << " Offset: " << getDieOffset() << "\n";
+ OS << " Tag: " << dwarf::TagString(getDieTag()) << "\n";
+}
+
+void DWARF5AccelTableStaticData::print(raw_ostream &OS) const {
+ OS << " Offset: " << getDieOffset() << "\n";
+ OS << " Tag: " << dwarf::TagString(getDieTag()) << "\n";
+}
+
+void AppleAccelTableOffsetData::print(raw_ostream &OS) const {
+ OS << " Offset: " << Die.getOffset() << "\n";
+}
+
+void AppleAccelTableTypeData::print(raw_ostream &OS) const {
+ OS << " Offset: " << Die.getOffset() << "\n";
+ OS << " Tag: " << dwarf::TagString(Die.getTag()) << "\n";
+}
+
+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
diff --git a/lib/CodeGen/AsmPrinter/AddressPool.cpp b/lib/CodeGen/AsmPrinter/AddressPool.cpp
index 59ed0324bdb0..4a226527cb5b 100644
--- a/lib/CodeGen/AsmPrinter/AddressPool.cpp
+++ b/lib/CodeGen/AsmPrinter/AddressPool.cpp
@@ -10,9 +10,9 @@
#include "AddressPool.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/CodeGen/AsmPrinter.h"
-#include "llvm/CodeGen/TargetLoweringObjectFile.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/MC/MCStreamer.h"
+#include "llvm/Target/TargetLoweringObjectFile.h"
#include <utility>
using namespace llvm;
diff --git a/lib/CodeGen/AsmPrinter/AddressPool.h b/lib/CodeGen/AsmPrinter/AddressPool.h
index 990a158d87cd..5350006bf744 100644
--- a/lib/CodeGen/AsmPrinter/AddressPool.h
+++ b/lib/CodeGen/AsmPrinter/AddressPool.h
@@ -39,7 +39,7 @@ class AddressPool {
public:
AddressPool() = default;
- /// \brief Returns the index into the address pool with the given
+ /// Returns the index into the address pool with the given
/// label/symbol.
unsigned getIndex(const MCSymbol *Sym, bool TLS = false);
diff --git a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
index d7995447592c..9bbc77b3056b 100644
--- a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -16,6 +16,7 @@
#include "CodeViewDebug.h"
#include "DwarfDebug.h"
#include "DwarfException.h"
+#include "WinCFGuard.h"
#include "WinException.h"
#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/APInt.h"
@@ -30,7 +31,6 @@
#include "llvm/ADT/Twine.h"
#include "llvm/Analysis/ConstantFolding.h"
#include "llvm/Analysis/EHPersonalities.h"
-#include "llvm/Analysis/ObjectUtils.h"
#include "llvm/Analysis/OptimizationRemarkEmitter.h"
#include "llvm/BinaryFormat/Dwarf.h"
#include "llvm/BinaryFormat/ELF.h"
@@ -39,6 +39,7 @@
#include "llvm/CodeGen/GCStrategy.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineConstantPool.h"
+#include "llvm/CodeGen/MachineDominators.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
@@ -54,7 +55,6 @@
#include "llvm/CodeGen/TargetFrameLowering.h"
#include "llvm/CodeGen/TargetInstrInfo.h"
#include "llvm/CodeGen/TargetLowering.h"
-#include "llvm/CodeGen/TargetLoweringObjectFile.h"
#include "llvm/CodeGen/TargetOpcodes.h"
#include "llvm/CodeGen/TargetRegisterInfo.h"
#include "llvm/CodeGen/TargetSubtargetInfo.h"
@@ -87,6 +87,7 @@
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCInst.h"
#include "llvm/MC/MCSection.h"
+#include "llvm/MC/MCSectionCOFF.h"
#include "llvm/MC/MCSectionELF.h"
#include "llvm/MC/MCSectionMachO.h"
#include "llvm/MC/MCStreamer.h"
@@ -107,6 +108,7 @@
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/Timer.h"
#include "llvm/Support/raw_ostream.h"
+#include "llvm/Target/TargetLoweringObjectFile.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetOptions.h"
#include <algorithm>
@@ -130,6 +132,8 @@ static const char *const DbgTimerName = "emit";
static const char *const DbgTimerDescription = "Debug Info Emission";
static const char *const EHTimerName = "write_exception";
static const char *const EHTimerDescription = "DWARF Exception Writer";
+static const char *const CFGuardName = "Control Flow Guard";
+static const char *const CFGuardDescription = "Control Flow Guard Tables";
static const char *const CodeViewLineTablesGroupName = "linetables";
static const char *const CodeViewLineTablesGroupDescription =
"CodeView Line Tables";
@@ -211,8 +215,10 @@ const DataLayout &AsmPrinter::getDataLayout() const {
}
// Do not use the cached DataLayout because some client use it without a Module
-// (llvm-dsymutil, llvm-dwarfdump).
-unsigned AsmPrinter::getPointerSize() const { return TM.getPointerSize(); }
+// (dsymutil, llvm-dwarfdump).
+unsigned AsmPrinter::getPointerSize() const {
+ return TM.getPointerSize(0); // FIXME: Default address space
+}
const MCSubtargetInfo &AsmPrinter::getSubtargetInfo() const {
assert(MF && "getSubtargetInfo requires a valid MachineFunction!");
@@ -234,7 +240,6 @@ void AsmPrinter::getAnalysisUsage(AnalysisUsage &AU) const {
AU.addRequired<MachineModuleInfo>();
AU.addRequired<MachineOptimizationRemarkEmitterPass>();
AU.addRequired<GCModuleInfo>();
- AU.addRequired<MachineLoopInfo>();
}
bool AsmPrinter::doInitialization(Module &M) {
@@ -246,7 +251,7 @@ bool AsmPrinter::doInitialization(Module &M) {
OutStreamer->InitSections(false);
- // Emit the version-min deplyment target directive if needed.
+ // Emit the version-min deployment target directive if needed.
//
// FIXME: If we end up with a collection of these sorts of Darwin-specific
// or ELF-specific things, it may make sense to have a platform helper class
@@ -291,8 +296,7 @@ bool AsmPrinter::doInitialization(Module &M) {
if (MAI->doesSupportDebugInformation()) {
bool EmitCodeView = MMI->getModule()->getCodeViewFlag();
- if (EmitCodeView && (TM.getTargetTriple().isKnownWindowsMSVCEnvironment() ||
- TM.getTargetTriple().isWindowsItaniumEnvironment())) {
+ if (EmitCodeView && TM.getTargetTriple().isOSWindows()) {
Handlers.push_back(HandlerInfo(new CodeViewDebug(this),
DbgTimerName, DbgTimerDescription,
CodeViewLineTablesGroupName,
@@ -350,10 +354,20 @@ bool AsmPrinter::doInitialization(Module &M) {
break;
}
break;
+ case ExceptionHandling::Wasm:
+ // TODO to prevent warning
+ break;
}
if (ES)
Handlers.push_back(HandlerInfo(ES, EHTimerName, EHTimerDescription,
DWARFGroupName, DWARFGroupDescription));
+
+ if (mdconst::extract_or_null<ConstantInt>(
+ MMI->getModule()->getModuleFlag("cfguard")))
+ Handlers.push_back(HandlerInfo(new WinCFGuard(this), CFGuardName,
+ CFGuardDescription, DWARFGroupName,
+ DWARFGroupDescription));
+
return false;
}
@@ -361,7 +375,7 @@ static bool canBeHidden(const GlobalValue *GV, const MCAsmInfo &MAI) {
if (!MAI.hasWeakDefCanBeHiddenDirective())
return false;
- return canBeOmittedFromSymbolTable(GV);
+ return GV->canBeOmittedFromSymbolTable();
}
void AsmPrinter::EmitLinkage(const GlobalValue *GV, MCSymbol *GVSym) const {
@@ -416,7 +430,7 @@ MCSymbol *AsmPrinter::getSymbol(const GlobalValue *GV) const {
/// EmitGlobalVariable - Emit the specified global variable to the .s file.
void AsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) {
- bool IsEmuTLSVar = TM.Options.EmulatedTLS && GV->isThreadLocal();
+ bool IsEmuTLSVar = TM.useEmulatedTLS() && GV->isThreadLocal();
assert(!(IsEmuTLSVar && GV->hasCommonLinkage()) &&
"No emulated TLS variables in the common section");
@@ -898,6 +912,30 @@ static bool emitDebugValueComment(const MachineInstr *MI, AsmPrinter &AP) {
return true;
}
+/// This method handles the target-independent form of DBG_LABEL, returning
+/// true if it was able to do so. A false return means the target will need
+/// to handle MI in EmitInstruction.
+static bool emitDebugLabelComment(const MachineInstr *MI, AsmPrinter &AP) {
+ if (MI->getNumOperands() != 1)
+ return false;
+
+ SmallString<128> Str;
+ raw_svector_ostream OS(Str);
+ OS << "DEBUG_LABEL: ";
+
+ const DILabel *V = MI->getDebugLabel();
+ if (auto *SP = dyn_cast<DISubprogram>(V->getScope())) {
+ StringRef Name = SP->getName();
+ if (!Name.empty())
+ OS << Name << ":";
+ }
+ OS << V->getName();
+
+ // NOTE: Want this comment at start of line, don't emit with AddComment.
+ AP.OutStreamer->emitRawComment(OS.str());
+ return true;
+}
+
AsmPrinter::CFIMoveType AsmPrinter::needsCFIMoves() const {
if (MAI->getExceptionHandlingType() == ExceptionHandling::DwarfCFI &&
MF->getFunction().needsUnwindTableEntry())
@@ -952,7 +990,8 @@ void AsmPrinter::emitStackSizeSection(const MachineFunction &MF) {
if (!MF.getTarget().Options.EmitStackSizeSection)
return;
- MCSection *StackSizeSection = getObjFileLowering().getStackSizesSection();
+ MCSection *StackSizeSection =
+ getObjFileLowering().getStackSizesSection(*getCurrentSection());
if (!StackSizeSection)
return;
@@ -964,10 +1003,9 @@ void AsmPrinter::emitStackSizeSection(const MachineFunction &MF) {
OutStreamer->PushSection();
OutStreamer->SwitchSection(StackSizeSection);
- const MCSymbol *FunctionSymbol = getSymbol(&MF.getFunction());
+ const MCSymbol *FunctionSymbol = getFunctionBegin();
uint64_t StackSize = FrameInfo.getStackSize();
- OutStreamer->EmitValue(MCSymbolRefExpr::create(FunctionSymbol, OutContext),
- /* size = */ 8);
+ OutStreamer->EmitSymbolValue(FunctionSymbol, TM.getProgramPointerSize());
OutStreamer->EmitULEB128IntValue(StackSize);
OutStreamer->PopSection();
@@ -996,6 +1034,24 @@ void AsmPrinter::EmitFunctionBody() {
bool ShouldPrintDebugScopes = MMI->hasDebugInfo();
+ if (isVerbose()) {
+ // Get MachineDominatorTree or compute it on the fly if it's unavailable
+ MDT = getAnalysisIfAvailable<MachineDominatorTree>();
+ if (!MDT) {
+ OwnedMDT = make_unique<MachineDominatorTree>();
+ OwnedMDT->getBase().recalculate(*MF);
+ MDT = OwnedMDT.get();
+ }
+
+ // Get MachineLoopInfo or compute it on the fly if it's unavailable
+ MLI = getAnalysisIfAvailable<MachineLoopInfo>();
+ if (!MLI) {
+ OwnedMLI = make_unique<MachineLoopInfo>();
+ OwnedMLI->getBase().analyze(MDT->getBase());
+ MLI = OwnedMLI.get();
+ }
+ }
+
// Print out code for the function.
bool HasAnyRealCode = false;
int NumInstsInFunction = 0;
@@ -1005,7 +1061,7 @@ void AsmPrinter::EmitFunctionBody() {
for (auto &MI : MBB) {
// Print the assembly for the instruction.
if (!MI.isPosition() && !MI.isImplicitDef() && !MI.isKill() &&
- !MI.isDebugValue()) {
+ !MI.isDebugInstr()) {
HasAnyRealCode = true;
++NumInstsInFunction;
}
@@ -1044,6 +1100,12 @@ void AsmPrinter::EmitFunctionBody() {
EmitInstruction(&MI);
}
break;
+ case TargetOpcode::DBG_LABEL:
+ if (isVerbose()) {
+ if (!emitDebugLabelComment(&MI, *this))
+ EmitInstruction(&MI);
+ }
+ break;
case TargetOpcode::IMPLICIT_DEF:
if (isVerbose()) emitImplicitDef(&MI);
break;
@@ -1155,7 +1217,7 @@ void AsmPrinter::EmitFunctionBody() {
OutStreamer->AddBlankLine();
}
-/// \brief Compute the number of Global Variables that uses a Constant.
+/// Compute the number of Global Variables that uses a Constant.
static unsigned getNumGlobalVariableUses(const Constant *C) {
if (!C)
return 0;
@@ -1170,7 +1232,7 @@ static unsigned getNumGlobalVariableUses(const Constant *C) {
return NumUses;
}
-/// \brief Only consider global GOT equivalents if at least one user is a
+/// Only consider global GOT equivalents if at least one user is a
/// cstexpr inside an initializer of another global variables. Also, don't
/// handle cstexpr inside instructions. During global variable emission,
/// candidates are skipped and are emitted later in case at least one cstexpr
@@ -1193,7 +1255,7 @@ static bool isGOTEquivalentCandidate(const GlobalVariable *GV,
return NumGOTEquivUsers > 0;
}
-/// \brief Unnamed constant global variables solely contaning a pointer to
+/// Unnamed constant global variables solely contaning a pointer to
/// another globals variable is equivalent to a GOT table entry; it contains the
/// the address of another symbol. Optimize it and replace accesses to these
/// "GOT equivalents" by using the GOT entry for the final global instead.
@@ -1214,7 +1276,7 @@ void AsmPrinter::computeGlobalGOTEquivs(Module &M) {
}
}
-/// \brief Constant expressions using GOT equivalent globals may not be eligible
+/// Constant expressions using GOT equivalent globals may not be eligible
/// for PC relative GOT entry conversion, in such cases we need to emit such
/// globals we previously omitted in EmitGlobalVariable.
void AsmPrinter::emitGlobalGOTEquivs() {
@@ -1312,7 +1374,7 @@ bool AsmPrinter::doFinalization(Module &M) {
const TargetLoweringObjectFile &TLOF = getObjFileLowering();
- TLOF.emitModuleMetadata(*OutStreamer, M, TM);
+ TLOF.emitModuleMetadata(*OutStreamer, M);
if (TM.getTargetTriple().isOSBinFormatELF()) {
MachineModuleInfoELF &MMIELF = MMI->getObjFileInfo<MachineModuleInfoELF>();
@@ -1323,6 +1385,7 @@ bool AsmPrinter::doFinalization(Module &M) {
OutStreamer->SwitchSection(TLOF.getDataSection());
const DataLayout &DL = M.getDataLayout();
+ EmitAlignment(Log2_32(DL.getPointerSize()));
for (const auto &Stub : Stubs) {
OutStreamer->EmitLabel(Stub.first);
OutStreamer->EmitSymbolValue(Stub.second.getPointer(),
@@ -1421,6 +1484,61 @@ bool AsmPrinter::doFinalization(Module &M) {
if (MCSection *S = MAI->getNonexecutableStackSection(OutContext))
OutStreamer->SwitchSection(S);
+ if (TM.getTargetTriple().isOSBinFormatCOFF()) {
+ // Emit /EXPORT: flags for each exported global as necessary.
+ const auto &TLOF = getObjFileLowering();
+ std::string Flags;
+
+ for (const GlobalValue &GV : M.global_values()) {
+ raw_string_ostream OS(Flags);
+ TLOF.emitLinkerFlagsForGlobal(OS, &GV);
+ OS.flush();
+ if (!Flags.empty()) {
+ OutStreamer->SwitchSection(TLOF.getDrectveSection());
+ OutStreamer->EmitBytes(Flags);
+ }
+ Flags.clear();
+ }
+
+ // Emit /INCLUDE: flags for each used global as necessary.
+ if (const auto *LU = M.getNamedGlobal("llvm.used")) {
+ assert(LU->hasInitializer() &&
+ "expected llvm.used to have an initializer");
+ assert(isa<ArrayType>(LU->getValueType()) &&
+ "expected llvm.used to be an array type");
+ if (const auto *A = cast<ConstantArray>(LU->getInitializer())) {
+ for (const Value *Op : A->operands()) {
+ const auto *GV =
+ cast<GlobalValue>(Op->stripPointerCastsNoFollowAliases());
+ // Global symbols with internal or private linkage are not visible to
+ // the linker, and thus would cause an error when the linker tried to
+ // preserve the symbol due to the `/include:` directive.
+ if (GV->hasLocalLinkage())
+ continue;
+
+ raw_string_ostream OS(Flags);
+ TLOF.emitLinkerFlagsForUsed(OS, GV);
+ OS.flush();
+
+ if (!Flags.empty()) {
+ OutStreamer->SwitchSection(TLOF.getDrectveSection());
+ OutStreamer->EmitBytes(Flags);
+ }
+ Flags.clear();
+ }
+ }
+ }
+ }
+
+ if (TM.Options.EmitAddrsig) {
+ // Emit address-significance attributes for all globals.
+ OutStreamer->EmitAddrsig();
+ for (const GlobalValue &GV : M.global_values())
+ if (!GV.isThreadLocal() && !GV.getName().startswith("llvm.") &&
+ !GV.hasAtLeastLocalUnnamedAddr())
+ OutStreamer->EmitAddrsigSym(getSymbol(&GV));
+ }
+
// Allow the target to emit any magic that it wants at the end of the file,
// after everything else has gone out.
EmitEndOfAsmFile(M);
@@ -1429,6 +1547,8 @@ bool AsmPrinter::doFinalization(Module &M) {
OutStreamer->Finish();
OutStreamer->reset();
+ OwnedMLI.reset();
+ OwnedMDT.reset();
return false;
}
@@ -1447,14 +1567,14 @@ void AsmPrinter::SetupMachineFunction(MachineFunction &MF) {
CurrentFnBegin = nullptr;
CurExceptionSym = nullptr;
bool NeedsLocalForSize = MAI->needsLocalForSize();
- if (needFuncLabelsForEHOrDebugInfo(MF, MMI) || NeedsLocalForSize) {
+ if (needFuncLabelsForEHOrDebugInfo(MF, MMI) || NeedsLocalForSize ||
+ MF.getTarget().Options.EmitStackSizeSection) {
CurrentFnBegin = createTempSymbol("func_begin");
if (NeedsLocalForSize)
CurrentFnSymForSize = CurrentFnBegin;
}
ORE = &getAnalysis<MachineOptimizationRemarkEmitterPass>().getORE();
- LI = &getAnalysis<MachineLoopInfo>();
const TargetSubtargetInfo &STI = MF.getSubtarget();
EnablePrintSchedInfo = PrintSchedule.getNumOccurrences()
@@ -1842,22 +1962,27 @@ void AsmPrinter::EmitModuleIdents(Module &M) {
// Emission and print routines
//
-/// EmitInt8 - Emit a byte directive and value.
+/// Emit a byte directive and value.
///
-void AsmPrinter::EmitInt8(int Value) const {
+void AsmPrinter::emitInt8(int Value) const {
OutStreamer->EmitIntValue(Value, 1);
}
-/// EmitInt16 - Emit a short directive and value.
-void AsmPrinter::EmitInt16(int Value) const {
+/// Emit a short directive and value.
+void AsmPrinter::emitInt16(int Value) const {
OutStreamer->EmitIntValue(Value, 2);
}
-/// EmitInt32 - Emit a long directive and value.
-void AsmPrinter::EmitInt32(int Value) const {
+/// Emit a long directive and value.
+void AsmPrinter::emitInt32(int Value) const {
OutStreamer->EmitIntValue(Value, 4);
}
+/// Emit a long long directive and value.
+void AsmPrinter::emitInt64(uint64_t Value) const {
+ OutStreamer->EmitIntValue(Value, 8);
+}
+
/// Emit something like ".long Hi-Lo" where the size in bytes of the directive
/// is specified by Size and Hi/Lo specify the labels. This implicitly uses
/// .set if it avoids relocations.
@@ -2069,6 +2194,7 @@ static void emitGlobalConstantImpl(const DataLayout &DL, const Constant *C,
uint64_t Offset = 0);
static void emitGlobalConstantFP(const ConstantFP *CFP, AsmPrinter &AP);
+static void emitGlobalConstantFP(APFloat APF, Type *ET, AsmPrinter &AP);
/// isRepeatedByteSequence - Determine whether the given value is
/// composed of a repeated sequence of identical bytes and return the
@@ -2146,13 +2272,15 @@ static void emitGlobalConstantDataSequential(const DataLayout &DL,
ElementByteSize);
}
} else {
+ Type *ET = CDS->getElementType();
for (unsigned I = 0, E = CDS->getNumElements(); I != E; ++I)
- emitGlobalConstantFP(cast<ConstantFP>(CDS->getElementAsConstant(I)), AP);
+ emitGlobalConstantFP(CDS->getElementAsAPFloat(I), ET, AP);
}
unsigned Size = DL.getTypeAllocSize(CDS->getType());
unsigned EmittedSize = DL.getTypeAllocSize(CDS->getType()->getElementType()) *
CDS->getNumElements();
+ assert(EmittedSize <= Size && "Size cannot be less than EmittedSize!");
if (unsigned Padding = Size - EmittedSize)
AP.OutStreamer->EmitZeros(Padding);
}
@@ -2216,17 +2344,17 @@ static void emitGlobalConstantStruct(const DataLayout &DL,
"Layout of constant struct may be incorrect!");
}
-static void emitGlobalConstantFP(const ConstantFP *CFP, AsmPrinter &AP) {
- APInt API = CFP->getValueAPF().bitcastToAPInt();
+static void emitGlobalConstantFP(APFloat APF, Type *ET, AsmPrinter &AP) {
+ APInt API = APF.bitcastToAPInt();
// First print a comment with what we think the original floating-point value
// should have been.
if (AP.isVerbose()) {
SmallString<8> StrVal;
- CFP->getValueAPF().toString(StrVal);
+ APF.toString(StrVal);
- if (CFP->getType())
- CFP->getType()->print(AP.OutStreamer->GetCommentOS());
+ if (ET)
+ ET->print(AP.OutStreamer->GetCommentOS());
else
AP.OutStreamer->GetCommentOS() << "Printing <null> Type";
AP.OutStreamer->GetCommentOS() << ' ' << StrVal << '\n';
@@ -2241,7 +2369,7 @@ static void emitGlobalConstantFP(const ConstantFP *CFP, AsmPrinter &AP) {
// PPC's long double has odd notions of endianness compared to how LLVM
// handles it: p[0] goes first for *big* endian on PPC.
- if (AP.getDataLayout().isBigEndian() && !CFP->getType()->isPPC_FP128Ty()) {
+ if (AP.getDataLayout().isBigEndian() && !ET->isPPC_FP128Ty()) {
int Chunk = API.getNumWords() - 1;
if (TrailingBytes)
@@ -2260,8 +2388,11 @@ static void emitGlobalConstantFP(const ConstantFP *CFP, AsmPrinter &AP) {
// Emit the tail padding for the long double.
const DataLayout &DL = AP.getDataLayout();
- AP.OutStreamer->EmitZeros(DL.getTypeAllocSize(CFP->getType()) -
- DL.getTypeStoreSize(CFP->getType()));
+ AP.OutStreamer->EmitZeros(DL.getTypeAllocSize(ET) - DL.getTypeStoreSize(ET));
+}
+
+static void emitGlobalConstantFP(const ConstantFP *CFP, AsmPrinter &AP) {
+ emitGlobalConstantFP(CFP->getValueAPF(), CFP->getType(), AP);
}
static void emitGlobalConstantLargeInt(const ConstantInt *CI, AsmPrinter &AP) {
@@ -2320,7 +2451,7 @@ static void emitGlobalConstantLargeInt(const ConstantInt *CI, AsmPrinter &AP) {
}
}
-/// \brief Transform a not absolute MCExpr containing a reference to a GOT
+/// Transform a not absolute MCExpr containing a reference to a GOT
/// equivalent global, by a target specific GOT pc relative access to the
/// final symbol.
static void handleIndirectSymViaGOTPCRel(AsmPrinter &AP, const MCExpr **ME,
@@ -2533,6 +2664,25 @@ MCSymbol *AsmPrinter::GetBlockAddressSymbol(const BasicBlock *BB) const {
/// GetCPISymbol - Return the symbol for the specified constant pool entry.
MCSymbol *AsmPrinter::GetCPISymbol(unsigned CPID) const {
+ if (getSubtargetInfo().getTargetTriple().isKnownWindowsMSVCEnvironment()) {
+ const MachineConstantPoolEntry &CPE =
+ MF->getConstantPool()->getConstants()[CPID];
+ if (!CPE.isMachineConstantPoolEntry()) {
+ const DataLayout &DL = MF->getDataLayout();
+ SectionKind Kind = CPE.getSectionKind(&DL);
+ const Constant *C = CPE.Val.ConstVal;
+ unsigned Align = CPE.Alignment;
+ if (const MCSectionCOFF *S = dyn_cast<MCSectionCOFF>(
+ getObjFileLowering().getSectionForConstant(DL, Kind, C, Align))) {
+ if (MCSymbol *Sym = S->getCOMDATSymbol()) {
+ if (Sym->isUndefined())
+ OutStreamer->EmitSymbolAttribute(Sym, MCSA_Global);
+ return Sym;
+ }
+ }
+ }
+ }
+
const DataLayout &DL = getDataLayout();
return OutContext.getOrCreateSymbol(Twine(DL.getPrivateGlobalPrefix()) +
"CPI" + Twine(getFunctionNumber()) + "_" +
@@ -2631,13 +2781,9 @@ static void emitBasicBlockLoopComments(const MachineBasicBlock &MBB,
void AsmPrinter::setupCodePaddingContext(const MachineBasicBlock &MBB,
MCCodePaddingContext &Context) const {
assert(MF != nullptr && "Machine function must be valid");
- assert(LI != nullptr && "Loop info must be valid");
Context.IsPaddingActive = !MF->hasInlineAsm() &&
!MF->getFunction().optForSize() &&
TM.getOptLevel() != CodeGenOpt::None;
- const MachineLoop *CurrentLoop = LI->getLoopFor(&MBB);
- Context.IsBasicBlockInsideInnermostLoop =
- CurrentLoop != nullptr && CurrentLoop->getSubLoops().empty();
Context.IsBasicBlockReachableViaFallthrough =
std::find(MBB.pred_begin(), MBB.pred_end(), MBB.getPrevNode()) !=
MBB.pred_end();
@@ -2689,7 +2835,9 @@ void AsmPrinter::EmitBasicBlockStart(const MachineBasicBlock &MBB) const {
OutStreamer->GetCommentOS() << '\n';
}
}
- emitBasicBlockLoopComments(MBB, LI, *this);
+
+ assert(MLI != nullptr && "MachineLoopInfo should has been computed");
+ emitBasicBlockLoopComments(MBB, MLI, *this);
}
// Print the main label for the block.
diff --git a/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp b/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp
index 08eb14e242c5..605588470670 100644
--- a/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp
+++ b/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp
@@ -17,7 +17,6 @@
#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/CodeGen/DIE.h"
#include "llvm/CodeGen/MachineFunction.h"
-#include "llvm/CodeGen/TargetLoweringObjectFile.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCRegisterInfo.h"
@@ -26,6 +25,7 @@
#include "llvm/MC/MCSymbol.h"
#include "llvm/MC/MachineLocation.h"
#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Target/TargetLoweringObjectFile.h"
#include "llvm/Target/TargetMachine.h"
using namespace llvm;
@@ -43,15 +43,6 @@ void AsmPrinter::EmitSLEB128(int64_t Value, const char *Desc) const {
OutStreamer->EmitSLEB128IntValue(Value);
}
-/// EmitULEB128 - emit the specified unsigned leb128 value.
-void AsmPrinter::EmitPaddedULEB128(uint64_t Value, unsigned PadTo,
- const char *Desc) const {
- if (isVerbose() && Desc)
- OutStreamer->AddComment(Desc);
-
- OutStreamer->EmitPaddedULEB128IntValue(Value, PadTo);
-}
-
void AsmPrinter::EmitULEB128(uint64_t Value, const char *Desc) const {
if (isVerbose() && Desc)
OutStreamer->AddComment(Desc);
@@ -59,6 +50,12 @@ void AsmPrinter::EmitULEB128(uint64_t Value, const char *Desc) const {
OutStreamer->EmitULEB128IntValue(Value);
}
+/// Emit something like ".uleb128 Hi-Lo".
+void AsmPrinter::EmitLabelDifferenceAsULEB128(const MCSymbol *Hi,
+ const MCSymbol *Lo) const {
+ OutStreamer->emitAbsoluteSymbolDiffAsULEB128(Hi, Lo);
+}
+
static const char *DecodeDWARFEncoding(unsigned Encoding) {
switch (Encoding) {
case dwarf::DW_EH_PE_absptr:
@@ -67,6 +64,10 @@ static const char *DecodeDWARFEncoding(unsigned Encoding) {
return "omit";
case dwarf::DW_EH_PE_pcrel:
return "pcrel";
+ case dwarf::DW_EH_PE_uleb128:
+ return "uleb128";
+ case dwarf::DW_EH_PE_sleb128:
+ return "sleb128";
case dwarf::DW_EH_PE_udata4:
return "udata4";
case dwarf::DW_EH_PE_udata8:
@@ -167,14 +168,19 @@ void AsmPrinter::emitDwarfSymbolReference(const MCSymbol *Label,
EmitLabelDifference(Label, Label->getSection().getBeginSymbol(), 4);
}
-void AsmPrinter::emitDwarfStringOffset(DwarfStringPoolEntryRef S) const {
+void AsmPrinter::emitDwarfStringOffset(DwarfStringPoolEntry S) const {
if (MAI->doesDwarfUseRelocationsAcrossSections()) {
- emitDwarfSymbolReference(S.getSymbol());
+ assert(S.Symbol && "No symbol available");
+ emitDwarfSymbolReference(S.Symbol);
return;
}
// Just emit the offset directly; no need for symbol math.
- EmitInt32(S.getOffset());
+ emitInt32(S.Offset);
+}
+
+void AsmPrinter::EmitDwarfOffset(const MCSymbol *Label, uint64_t Offset) const {
+ EmitLabelPlusOffset(Label, Offset, MAI->getCodePointerSize());
}
//===----------------------------------------------------------------------===//
@@ -252,7 +258,7 @@ void AsmPrinter::emitDwarfDIE(const DIE &Die) const {
emitDwarfDIE(Child);
OutStreamer->AddComment("End Of Children Mark");
- EmitInt8(0);
+ emitInt8(0);
}
}
diff --git a/lib/CodeGen/AsmPrinter/AsmPrinterHandler.h b/lib/CodeGen/AsmPrinter/AsmPrinterHandler.h
index 638226e90a7a..f5ac95a20b10 100644
--- a/lib/CodeGen/AsmPrinter/AsmPrinterHandler.h
+++ b/lib/CodeGen/AsmPrinter/AsmPrinterHandler.h
@@ -27,29 +27,29 @@ class MCSymbol;
typedef MCSymbol *ExceptionSymbolProvider(AsmPrinter *Asm);
-/// \brief Collects and handles AsmPrinter objects required to build debug
+/// Collects and handles AsmPrinter objects required to build debug
/// or EH information.
class AsmPrinterHandler {
public:
virtual ~AsmPrinterHandler();
- /// \brief For symbols that have a size designated (e.g. common symbols),
+ /// For symbols that have a size designated (e.g. common symbols),
/// this tracks that size.
virtual void setSymbolSize(const MCSymbol *Sym, uint64_t Size) = 0;
- /// \brief Emit all sections that should come after the content.
+ /// Emit all sections that should come after the content.
virtual void endModule() = 0;
- /// \brief Gather pre-function debug information.
+ /// Gather pre-function debug information.
/// Every beginFunction(MF) call should be followed by an endFunction(MF)
/// call.
virtual void beginFunction(const MachineFunction *MF) = 0;
- // \brief Emit any of function marker (like .cfi_endproc). This is called
+ // Emit any of function marker (like .cfi_endproc). This is called
// before endFunction and cannot switch sections.
virtual void markFunctionEnd();
- /// \brief Gather post-function debug information.
+ /// Gather post-function debug information.
/// Please note that some AsmPrinter implementations may not call
/// beginFunction at all.
virtual void endFunction(const MachineFunction *MF) = 0;
@@ -58,15 +58,15 @@ public:
ExceptionSymbolProvider ESP) {}
virtual void endFragment() {}
- /// \brief Emit target-specific EH funclet machinery.
+ /// Emit target-specific EH funclet machinery.
virtual void beginFunclet(const MachineBasicBlock &MBB,
MCSymbol *Sym = nullptr) {}
virtual void endFunclet() {}
- /// \brief Process beginning of an instruction.
+ /// Process beginning of an instruction.
virtual void beginInstruction(const MachineInstr *MI) = 0;
- /// \brief Process end of an instruction.
+ /// Process end of an instruction.
virtual void endInstruction() = 0;
};
} // End of namespace llvm
diff --git a/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp b/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp
index 04a72ba3d738..4159eb19423a 100644
--- a/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp
+++ b/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp
@@ -132,6 +132,9 @@ void AsmPrinter::EmitInlineAsm(StringRef Str, const MCSubtargetInfo &STI,
std::unique_ptr<MCAsmParser> Parser(
createMCAsmParser(SrcMgr, OutContext, *OutStreamer, *MAI, BufNum));
+ // Do not use assembler-level information for parsing inline assembly.
+ OutStreamer->setUseAssemblerInfoForParsing(false);
+
// We create a new MCInstrInfo here since we might be at the module level
// and not have a MachineFunction to initialize the TargetInstrInfo from and
// we only need MCInstrInfo for asm parsing. We create one unconditionally
diff --git a/lib/CodeGen/AsmPrinter/ByteStreamer.h b/lib/CodeGen/AsmPrinter/ByteStreamer.h
index aaf6180c9404..2163cc7e3e11 100644
--- a/lib/CodeGen/AsmPrinter/ByteStreamer.h
+++ b/lib/CodeGen/AsmPrinter/ByteStreamer.h
@@ -43,7 +43,7 @@ public:
APByteStreamer(AsmPrinter &Asm) : AP(Asm) {}
void EmitInt8(uint8_t Byte, const Twine &Comment) override {
AP.OutStreamer->AddComment(Comment);
- AP.EmitInt8(Byte);
+ AP.emitInt8(Byte);
}
void EmitSLEB128(uint64_t DWord, const Twine &Comment) override {
AP.OutStreamer->AddComment(Comment);
@@ -76,7 +76,7 @@ private:
SmallVectorImpl<char> &Buffer;
SmallVectorImpl<std::string> &Comments;
- /// \brief Only verbose textual output needs comments. This will be set to
+ /// Only verbose textual output needs comments. This will be set to
/// true for that case, and false otherwise. If false, comments passed in to
/// the emit methods will be ignored.
bool GenerateComments;
@@ -93,15 +93,27 @@ public:
}
void EmitSLEB128(uint64_t DWord, const Twine &Comment) override {
raw_svector_ostream OSE(Buffer);
- encodeSLEB128(DWord, OSE);
- if (GenerateComments)
+ unsigned Length = encodeSLEB128(DWord, OSE);
+ if (GenerateComments) {
Comments.push_back(Comment.str());
+ // Add some empty comments to keep the Buffer and Comments vectors aligned
+ // with each other.
+ for (size_t i = 1; i < Length; ++i)
+ Comments.push_back("");
+
+ }
}
void EmitULEB128(uint64_t DWord, const Twine &Comment) override {
raw_svector_ostream OSE(Buffer);
- encodeULEB128(DWord, OSE);
- if (GenerateComments)
+ unsigned Length = encodeULEB128(DWord, OSE);
+ if (GenerateComments) {
Comments.push_back(Comment.str());
+ // Add some empty comments to keep the Buffer and Comments vectors aligned
+ // with each other.
+ for (size_t i = 1; i < Length; ++i)
+ Comments.push_back("");
+
+ }
}
};
diff --git a/lib/CodeGen/AsmPrinter/CMakeLists.txt b/lib/CodeGen/AsmPrinter/CMakeLists.txt
index 05c6a28bbcac..0f8c24158ee2 100644
--- a/lib/CodeGen/AsmPrinter/CMakeLists.txt
+++ b/lib/CodeGen/AsmPrinter/CMakeLists.txt
@@ -1,4 +1,5 @@
add_llvm_library(LLVMAsmPrinter
+ AccelTable.cpp
AddressPool.cpp
ARMException.cpp
AsmPrinter.cpp
@@ -9,7 +10,6 @@ add_llvm_library(LLVMAsmPrinter
DebugLocStream.cpp
DIE.cpp
DIEHash.cpp
- DwarfAccelTable.cpp
DwarfCFIException.cpp
DwarfCompileUnit.cpp
DwarfDebug.cpp
@@ -20,6 +20,7 @@ add_llvm_library(LLVMAsmPrinter
EHStreamer.cpp
ErlangGCPrinter.cpp
OcamlGCPrinter.cpp
+ WinCFGuard.cpp
WinException.cpp
CodeViewDebug.cpp
diff --git a/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp b/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
index 1d0a003dc50a..8c5c5478d01a 100644
--- a/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
+++ b/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
@@ -36,7 +36,6 @@
#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/CodeGen/MachineOperand.h"
#include "llvm/CodeGen/TargetFrameLowering.h"
-#include "llvm/CodeGen/TargetLoweringObjectFile.h"
#include "llvm/CodeGen/TargetRegisterInfo.h"
#include "llvm/CodeGen/TargetSubtargetInfo.h"
#include "llvm/Config/llvm-config.h"
@@ -75,6 +74,7 @@
#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/SMLoc.h"
#include "llvm/Support/ScopedPrinter.h"
+#include "llvm/Target/TargetLoweringObjectFile.h"
#include "llvm/Target/TargetMachine.h"
#include <algorithm>
#include <cassert>
@@ -114,6 +114,16 @@ StringRef CodeViewDebug::getFullFilepath(const DIFile *File) {
StringRef Dir = File->getDirectory(), Filename = File->getFilename();
+ // If this is a Unix-style path, just use it as is. Don't try to canonicalize
+ // it textually because one of the path components could be a symlink.
+ if (!Dir.empty() && Dir[0] == '/') {
+ Filepath = Dir;
+ if (Dir.back() != '/')
+ Filepath += '/';
+ Filepath += Filename;
+ return Filepath;
+ }
+
// Clang emits directory and relative filename info into the IR, but CodeView
// operates on full paths. We could change Clang to emit full paths too, but
// that would increase the IR size and probably not needed for other users.
@@ -165,14 +175,21 @@ unsigned CodeViewDebug::maybeRecordFile(const DIFile *F) {
auto Insertion = FileIdMap.insert(std::make_pair(FullPath, NextId));
if (Insertion.second) {
// We have to compute the full filepath and emit a .cv_file directive.
- std::string Checksum = fromHex(F->getChecksum());
- void *CKMem = OS.getContext().allocate(Checksum.size(), 1);
- memcpy(CKMem, Checksum.data(), Checksum.size());
- ArrayRef<uint8_t> ChecksumAsBytes(reinterpret_cast<const uint8_t *>(CKMem),
- Checksum.size());
- DIFile::ChecksumKind ChecksumKind = F->getChecksumKind();
+ ArrayRef<uint8_t> ChecksumAsBytes;
+ FileChecksumKind CSKind = FileChecksumKind::None;
+ if (F->getChecksum()) {
+ std::string Checksum = fromHex(F->getChecksum()->Value);
+ void *CKMem = OS.getContext().allocate(Checksum.size(), 1);
+ memcpy(CKMem, Checksum.data(), Checksum.size());
+ ChecksumAsBytes = ArrayRef<uint8_t>(
+ reinterpret_cast<const uint8_t *>(CKMem), Checksum.size());
+ switch (F->getChecksum()->Kind) {
+ case DIFile::CSK_MD5: CSKind = FileChecksumKind::MD5; break;
+ case DIFile::CSK_SHA1: CSKind = FileChecksumKind::SHA1; break;
+ }
+ }
bool Success = OS.EmitCVFileDirective(NextId, FullPath, ChecksumAsBytes,
- static_cast<unsigned>(ChecksumKind));
+ static_cast<unsigned>(CSKind));
(void)Success;
assert(Success && ".cv_file directive failed");
}
@@ -358,15 +375,15 @@ unsigned CodeViewDebug::getPointerSizeInBytes() {
}
void CodeViewDebug::recordLocalVariable(LocalVariable &&Var,
- const DILocation *InlinedAt) {
- if (InlinedAt) {
+ const LexicalScope *LS) {
+ if (const DILocation *InlinedAt = LS->getInlinedAt()) {
// This variable was inlined. Associate it with the InlineSite.
const DISubprogram *Inlinee = Var.DIVar->getScope()->getSubprogram();
InlineSite &Site = getInlineSite(InlinedAt, Inlinee);
Site.InlinedLocals.emplace_back(Var);
} else {
- // This variable goes in the main ProcSym.
- CurFn->Locals.emplace_back(Var);
+ // This variable goes into the corresponding lexical scope.
+ ScopeVariables[LS].emplace_back(Var);
}
}
@@ -463,7 +480,7 @@ void CodeViewDebug::endModule() {
// Emit per-function debug information.
for (auto &P : FnDebugInfo)
if (!P.first->isDeclarationForLinker())
- emitDebugInfoForFunction(P.first, P.second);
+ emitDebugInfoForFunction(P.first, *P.second);
// Emit global variable debug information.
setCurrentSubprogram(nullptr);
@@ -501,12 +518,12 @@ void CodeViewDebug::endModule() {
clear();
}
-static void emitNullTerminatedSymbolName(MCStreamer &OS, StringRef S) {
+static void emitNullTerminatedSymbolName(MCStreamer &OS, StringRef S,
+ unsigned MaxFixedRecordLength = 0xF00) {
// The maximum CV record length is 0xFF00. Most of the strings we emit appear
// after a fixed length portion of the record. The fixed length portion should
// always be less than 0xF00 (3840) bytes, so truncate the string so that the
// overall record size is less than the maximum allowed.
- unsigned MaxFixedRecordLength = 0xF00;
SmallString<32> NullTerminatedString(
S.take_front(MaxRecordLength - MaxFixedRecordLength - 1));
NullTerminatedString.push_back('\0');
@@ -517,7 +534,7 @@ void CodeViewDebug::emitTypeInformation() {
if (TypeTable.empty())
return;
- // Start the .debug$T section with 0x4.
+ // Start the .debug$T or .debug$P section with 0x4.
OS.SwitchSection(Asm->getObjFileLowering().getCOFFDebugTypesSection());
emitCodeViewMagicVersion();
@@ -572,7 +589,7 @@ void CodeViewDebug::emitTypeGlobalHashes() {
OS.AddComment("Section Version");
OS.EmitIntValue(0, 2);
OS.AddComment("Hash Algorithm");
- OS.EmitIntValue(uint16_t(GlobalTypeHashAlg::SHA1), 2);
+ OS.EmitIntValue(uint16_t(GlobalTypeHashAlg::SHA1_8), 2);
TypeIndex TI(TypeIndex::FirstNonSimpleIndex);
for (const auto &GHR : TypeTable.hashes()) {
@@ -585,7 +602,7 @@ void CodeViewDebug::emitTypeGlobalHashes() {
OS.AddComment(Comment);
++TI;
}
- assert(GHR.Hash.size() % 20 == 0);
+ assert(GHR.Hash.size() == 8);
StringRef S(reinterpret_cast<const char *>(GHR.Hash.data()),
GHR.Hash.size());
OS.EmitBinaryData(S);
@@ -821,10 +838,61 @@ void CodeViewDebug::switchToDebugSectionForSymbol(const MCSymbol *GVSym) {
emitCodeViewMagicVersion();
}
+// Emit an S_THUNK32/S_END symbol pair for a thunk routine.
+// The only supported thunk ordinal is currently the standard type.
+void CodeViewDebug::emitDebugInfoForThunk(const Function *GV,
+ FunctionInfo &FI,
+ const MCSymbol *Fn) {
+ std::string FuncName = GlobalValue::dropLLVMManglingEscape(GV->getName());
+ const ThunkOrdinal ordinal = ThunkOrdinal::Standard; // Only supported kind.
+
+ OS.AddComment("Symbol subsection for " + Twine(FuncName));
+ MCSymbol *SymbolsEnd = beginCVSubsection(DebugSubsectionKind::Symbols);
+
+ // Emit S_THUNK32
+ MCSymbol *ThunkRecordBegin = MMI->getContext().createTempSymbol(),
+ *ThunkRecordEnd = MMI->getContext().createTempSymbol();
+ OS.AddComment("Record length");
+ OS.emitAbsoluteSymbolDiff(ThunkRecordEnd, ThunkRecordBegin, 2);
+ OS.EmitLabel(ThunkRecordBegin);
+ OS.AddComment("Record kind: S_THUNK32");
+ OS.EmitIntValue(unsigned(SymbolKind::S_THUNK32), 2);
+ OS.AddComment("PtrParent");
+ OS.EmitIntValue(0, 4);
+ OS.AddComment("PtrEnd");
+ OS.EmitIntValue(0, 4);
+ OS.AddComment("PtrNext");
+ OS.EmitIntValue(0, 4);
+ OS.AddComment("Thunk section relative address");
+ OS.EmitCOFFSecRel32(Fn, /*Offset=*/0);
+ OS.AddComment("Thunk section index");
+ OS.EmitCOFFSectionIndex(Fn);
+ OS.AddComment("Code size");
+ OS.emitAbsoluteSymbolDiff(FI.End, Fn, 2);
+ OS.AddComment("Ordinal");
+ OS.EmitIntValue(unsigned(ordinal), 1);
+ OS.AddComment("Function name");
+ emitNullTerminatedSymbolName(OS, FuncName);
+ // Additional fields specific to the thunk ordinal would go here.
+ OS.EmitLabel(ThunkRecordEnd);
+
+ // Local variables/inlined routines are purposely omitted here. The point of
+ // marking this as a thunk is so Visual Studio will NOT stop in this routine.
+
+ // Emit S_PROC_ID_END
+ const unsigned RecordLengthForSymbolEnd = 2;
+ OS.AddComment("Record length");
+ OS.EmitIntValue(RecordLengthForSymbolEnd, 2);
+ OS.AddComment("Record kind: S_PROC_ID_END");
+ OS.EmitIntValue(unsigned(SymbolKind::S_PROC_ID_END), 2);
+
+ endCVSubsection(SymbolsEnd);
+}
+
void CodeViewDebug::emitDebugInfoForFunction(const Function *GV,
FunctionInfo &FI) {
- // For each function there is a separate subsection
- // which holds the PC to file:line table.
+ // For each function there is a separate subsection which holds the PC to
+ // file:line table.
const MCSymbol *Fn = Asm->getSymbol(GV);
assert(Fn);
@@ -836,6 +904,11 @@ void CodeViewDebug::emitDebugInfoForFunction(const Function *GV,
assert(SP);
setCurrentSubprogram(SP);
+ if (SP->isThunk()) {
+ emitDebugInfoForThunk(GV, FI, Fn);
+ return;
+ }
+
// If we have a display name, build the fully qualified name by walking the
// chain of scopes.
if (!SP->getName().empty())
@@ -898,6 +971,7 @@ void CodeViewDebug::emitDebugInfoForFunction(const Function *GV,
OS.EmitLabel(ProcRecordEnd);
emitLocalVariableList(FI.Locals);
+ emitLexicalBlockList(FI.ChildBlocks, FI);
// Emit inlined call site information. Only emit functions inlined directly
// into the parent function. We'll emit the other sites recursively as part
@@ -1018,7 +1092,7 @@ void CodeViewDebug::collectVariableInfoFromMFTable(
LocalVariable Var;
Var.DIVar = VI.Var;
Var.DefRanges.emplace_back(std::move(DefRange));
- recordLocalVariable(std::move(Var), VI.Loc->getInlinedAt());
+ recordLocalVariable(std::move(Var), Scope);
}
}
@@ -1100,7 +1174,7 @@ void CodeViewDebug::calculateRanges(
auto J = std::next(I);
const DIExpression *DIExpr = DVInst->getDebugExpression();
while (J != E &&
- !fragmentsOverlap(DIExpr, J->first->getDebugExpression()))
+ !DIExpr->fragmentsOverlap(J->first->getDebugExpression()))
++J;
if (J != E)
End = getLabelBeforeInsn(J->first);
@@ -1149,14 +1223,15 @@ void CodeViewDebug::collectVariableInfo(const DISubprogram *SP) {
Var.DIVar = DIVar;
calculateRanges(Var, Ranges);
- recordLocalVariable(std::move(Var), InlinedAt);
+ recordLocalVariable(std::move(Var), Scope);
}
}
void CodeViewDebug::beginFunctionImpl(const MachineFunction *MF) {
const Function &GV = MF->getFunction();
- assert(FnDebugInfo.count(&GV) == false);
- CurFn = &FnDebugInfo[&GV];
+ auto Insertion = FnDebugInfo.insert({&GV, llvm::make_unique<FunctionInfo>()});
+ assert(Insertion.second && "function already has info");
+ CurFn = Insertion.first->second.get();
CurFn->FuncId = NextFuncId++;
CurFn->Begin = Asm->getFunctionBegin();
@@ -1261,6 +1336,7 @@ TypeIndex CodeViewDebug::lowerType(const DIType *Ty, const DIType *ClassTy) {
return lowerTypePointer(cast<DIDerivedType>(Ty));
case dwarf::DW_TAG_ptr_to_member_type:
return lowerTypeMemberPointer(cast<DIDerivedType>(Ty));
+ case dwarf::DW_TAG_restrict_type:
case dwarf::DW_TAG_const_type:
case dwarf::DW_TAG_volatile_type:
// TODO: add support for DW_TAG_atomic_type here
@@ -1281,6 +1357,8 @@ TypeIndex CodeViewDebug::lowerType(const DIType *Ty, const DIType *ClassTy) {
return lowerTypeClass(cast<DICompositeType>(Ty));
case dwarf::DW_TAG_union_type:
return lowerTypeUnion(cast<DICompositeType>(Ty));
+ case dwarf::DW_TAG_unspecified_type:
+ return TypeIndex::None();
default:
// Use the null type index.
return TypeIndex();
@@ -1308,7 +1386,7 @@ TypeIndex CodeViewDebug::lowerTypeArray(const DICompositeType *Ty) {
DITypeRef ElementTypeRef = Ty->getBaseType();
TypeIndex ElementTypeIndex = getTypeIndex(ElementTypeRef);
// IndexType is size_t, which depends on the bitness of the target.
- TypeIndex IndexType = Asm->TM.getPointerSize() == 8
+ TypeIndex IndexType = getPointerSizeInBytes() == 8
? TypeIndex(SimpleTypeKind::UInt64Quad)
: TypeIndex(SimpleTypeKind::UInt32Long);
@@ -1323,7 +1401,9 @@ TypeIndex CodeViewDebug::lowerTypeArray(const DICompositeType *Ty) {
const DISubrange *Subrange = cast<DISubrange>(Element);
assert(Subrange->getLowerBound() == 0 &&
"codeview doesn't support subranges with lower bounds");
- int64_t Count = Subrange->getCount();
+ int64_t Count = -1;
+ if (auto *CI = Subrange->getCount().dyn_cast<ConstantInt*>())
+ Count = CI->getSExtValue();
// Forward declarations of arrays without a size and VLAs use a count of -1.
// Emit a count of zero in these cases to match what MSVC does for arrays
@@ -1441,12 +1521,13 @@ TypeIndex CodeViewDebug::lowerTypeBasic(const DIBasicType *Ty) {
return TypeIndex(STK);
}
-TypeIndex CodeViewDebug::lowerTypePointer(const DIDerivedType *Ty) {
+TypeIndex CodeViewDebug::lowerTypePointer(const DIDerivedType *Ty,
+ PointerOptions PO) {
TypeIndex PointeeTI = getTypeIndex(Ty->getBaseType());
- // Pointers to simple types can use SimpleTypeMode, rather than having a
- // dedicated pointer type record.
- if (PointeeTI.isSimple() &&
+ // Pointers to simple types without any options can use SimpleTypeMode, rather
+ // than having a dedicated pointer type record.
+ if (PointeeTI.isSimple() && PO == PointerOptions::None &&
PointeeTI.getSimpleMode() == SimpleTypeMode::Direct &&
Ty->getTag() == dwarf::DW_TAG_pointer_type) {
SimpleTypeMode Mode = Ty->getSizeInBits() == 64
@@ -1470,10 +1551,7 @@ TypeIndex CodeViewDebug::lowerTypePointer(const DIDerivedType *Ty) {
PM = PointerMode::RValueReference;
break;
}
- // FIXME: MSVC folds qualifiers into PointerOptions in the context of a method
- // 'this' pointer, but not normal contexts. Figure out what we're supposed to
- // do.
- PointerOptions PO = PointerOptions::None;
+
PointerRecord PR(PointeeTI, PK, PM, PO, Ty->getSizeInBits() / 8);
return TypeTable.writeLeafType(PR);
}
@@ -1511,16 +1589,17 @@ translatePtrToMemberRep(unsigned SizeInBytes, bool IsPMF, unsigned Flags) {
llvm_unreachable("invalid ptr to member representation");
}
-TypeIndex CodeViewDebug::lowerTypeMemberPointer(const DIDerivedType *Ty) {
+TypeIndex CodeViewDebug::lowerTypeMemberPointer(const DIDerivedType *Ty,
+ PointerOptions PO) {
assert(Ty->getTag() == dwarf::DW_TAG_ptr_to_member_type);
TypeIndex ClassTI = getTypeIndex(Ty->getClassType());
TypeIndex PointeeTI = getTypeIndex(Ty->getBaseType(), Ty->getClassType());
- PointerKind PK = Asm->TM.getPointerSize() == 8 ? PointerKind::Near64
- : PointerKind::Near32;
+ PointerKind PK = getPointerSizeInBytes() == 8 ? PointerKind::Near64
+ : PointerKind::Near32;
bool IsPMF = isa<DISubroutineType>(Ty->getBaseType());
PointerMode PM = IsPMF ? PointerMode::PointerToMemberFunction
: PointerMode::PointerToDataMember;
- PointerOptions PO = PointerOptions::None; // FIXME
+
assert(Ty->getSizeInBits() / 8 <= 0xff && "pointer size too big");
uint8_t SizeInBytes = Ty->getSizeInBits() / 8;
MemberPointerInfo MPI(
@@ -1545,6 +1624,7 @@ static CallingConvention dwarfCCToCodeView(unsigned DwarfCC) {
TypeIndex CodeViewDebug::lowerTypeModifier(const DIDerivedType *Ty) {
ModifierOptions Mods = ModifierOptions::None;
+ PointerOptions PO = PointerOptions::None;
bool IsModifier = true;
const DIType *BaseTy = Ty;
while (IsModifier && BaseTy) {
@@ -1552,9 +1632,16 @@ TypeIndex CodeViewDebug::lowerTypeModifier(const DIDerivedType *Ty) {
switch (BaseTy->getTag()) {
case dwarf::DW_TAG_const_type:
Mods |= ModifierOptions::Const;
+ PO |= PointerOptions::Const;
break;
case dwarf::DW_TAG_volatile_type:
Mods |= ModifierOptions::Volatile;
+ PO |= PointerOptions::Volatile;
+ break;
+ case dwarf::DW_TAG_restrict_type:
+ // Only pointer types be marked with __restrict. There is no known flag
+ // for __restrict in LF_MODIFIER records.
+ PO |= PointerOptions::Restrict;
break;
default:
IsModifier = false;
@@ -1563,7 +1650,31 @@ TypeIndex CodeViewDebug::lowerTypeModifier(const DIDerivedType *Ty) {
if (IsModifier)
BaseTy = cast<DIDerivedType>(BaseTy)->getBaseType().resolve();
}
+
+ // Check if the inner type will use an LF_POINTER record. If so, the
+ // qualifiers will go in the LF_POINTER record. This comes up for types like
+ // 'int *const' and 'int *__restrict', not the more common cases like 'const
+ // char *'.
+ if (BaseTy) {
+ switch (BaseTy->getTag()) {
+ case dwarf::DW_TAG_pointer_type:
+ case dwarf::DW_TAG_reference_type:
+ case dwarf::DW_TAG_rvalue_reference_type:
+ return lowerTypePointer(cast<DIDerivedType>(BaseTy), PO);
+ case dwarf::DW_TAG_ptr_to_member_type:
+ return lowerTypeMemberPointer(cast<DIDerivedType>(BaseTy), PO);
+ default:
+ break;
+ }
+ }
+
TypeIndex ModifiedTI = getTypeIndex(BaseTy);
+
+ // Return the base type index if there aren't any modifiers. For example, the
+ // metadata could contain restrict wrappers around non-pointer types.
+ if (Mods == ModifierOptions::None)
+ return ModifiedTI;
+
ModifierRecord MR(ModifiedTI, Mods);
return TypeTable.writeLeafType(MR);
}
@@ -1573,6 +1684,11 @@ TypeIndex CodeViewDebug::lowerTypeFunction(const DISubroutineType *Ty) {
for (DITypeRef ArgTypeRef : Ty->getTypeArray())
ReturnAndArgTypeIndices.push_back(getTypeIndex(ArgTypeRef));
+ // MSVC uses type none for variadic argument.
+ if (ReturnAndArgTypeIndices.size() > 1 &&
+ ReturnAndArgTypeIndices.back() == TypeIndex::Void()) {
+ ReturnAndArgTypeIndices.back() = TypeIndex::None();
+ }
TypeIndex ReturnTypeIndex = TypeIndex::Void();
ArrayRef<TypeIndex> ArgTypeIndices = None;
if (!ReturnAndArgTypeIndices.empty()) {
@@ -1602,6 +1718,11 @@ TypeIndex CodeViewDebug::lowerTypeMemberFunction(const DISubroutineType *Ty,
for (DITypeRef ArgTypeRef : Ty->getTypeArray())
ReturnAndArgTypeIndices.push_back(getTypeIndex(ArgTypeRef));
+ // MSVC uses type none for variadic argument.
+ if (ReturnAndArgTypeIndices.size() > 1 &&
+ ReturnAndArgTypeIndices.back() == TypeIndex::Void()) {
+ ReturnAndArgTypeIndices.back() = TypeIndex::None();
+ }
TypeIndex ReturnTypeIndex = TypeIndex::Void();
ArrayRef<TypeIndex> ArgTypeIndices = None;
if (!ReturnAndArgTypeIndices.empty()) {
@@ -1716,6 +1837,26 @@ static ClassOptions getCommonClassOptions(const DICompositeType *Ty) {
return CO;
}
+void CodeViewDebug::addUDTSrcLine(const DIType *Ty, TypeIndex TI) {
+ switch (Ty->getTag()) {
+ case dwarf::DW_TAG_class_type:
+ case dwarf::DW_TAG_structure_type:
+ case dwarf::DW_TAG_union_type:
+ case dwarf::DW_TAG_enumeration_type:
+ break;
+ default:
+ return;
+ }
+
+ if (const auto *File = Ty->getFile()) {
+ StringIdRecord SIDR(TypeIndex(0x0), getFullFilepath(File));
+ TypeIndex SIDI = TypeTable.writeLeafType(SIDR);
+
+ UdtSourceLineRecord USLR(TI, SIDI, Ty->getLine());
+ TypeTable.writeLeafType(USLR);
+ }
+}
+
TypeIndex CodeViewDebug::lowerTypeEnum(const DICompositeType *Ty) {
ClassOptions CO = getCommonClassOptions(Ty);
TypeIndex FTI;
@@ -1744,7 +1885,11 @@ TypeIndex CodeViewDebug::lowerTypeEnum(const DICompositeType *Ty) {
EnumRecord ER(EnumeratorCount, CO, FTI, FullName, Ty->getIdentifier(),
getTypeIndex(Ty->getBaseType()));
- return TypeTable.writeLeafType(ER);
+ TypeIndex EnumTI = TypeTable.writeLeafType(ER);
+
+ addUDTSrcLine(Ty, EnumTI);
+
+ return EnumTI;
}
//===----------------------------------------------------------------------===//
@@ -1793,12 +1938,33 @@ void CodeViewDebug::collectMemberInfo(ClassInfo &Info,
Info.Members.push_back({DDTy, 0});
return;
}
- // An unnamed member must represent a nested struct or union. Add all the
- // indirect fields to the current record.
+
+ // An unnamed member may represent a nested struct or union. Attempt to
+ // interpret the unnamed member as a DICompositeType possibly wrapped in
+ // qualifier types. Add all the indirect fields to the current record if that
+ // succeeds, and drop the member if that fails.
assert((DDTy->getOffsetInBits() % 8) == 0 && "Unnamed bitfield member!");
uint64_t Offset = DDTy->getOffsetInBits();
const DIType *Ty = DDTy->getBaseType().resolve();
- const DICompositeType *DCTy = cast<DICompositeType>(Ty);
+ bool FullyResolved = false;
+ while (!FullyResolved) {
+ switch (Ty->getTag()) {
+ case dwarf::DW_TAG_const_type:
+ case dwarf::DW_TAG_volatile_type:
+ // FIXME: we should apply the qualifier types to the indirect fields
+ // rather than dropping them.
+ Ty = cast<DIDerivedType>(Ty)->getBaseType().resolve();
+ break;
+ default:
+ FullyResolved = true;
+ break;
+ }
+ }
+
+ const DICompositeType *DCTy = dyn_cast<DICompositeType>(Ty);
+ if (!DCTy)
+ return;
+
ClassInfo NestedInfo = collectClassInfo(DCTy);
for (const ClassInfo::MemberInfo &IndirectField : NestedInfo.Members)
Info.Members.push_back(
@@ -1838,7 +2004,28 @@ ClassInfo CodeViewDebug::collectClassInfo(const DICompositeType *Ty) {
return Info;
}
+static bool shouldAlwaysEmitCompleteClassType(const DICompositeType *Ty) {
+ // This routine is used by lowerTypeClass and lowerTypeUnion to determine
+ // if a complete type should be emitted instead of a forward reference.
+ return Ty->getName().empty() && Ty->getIdentifier().empty() &&
+ !Ty->isForwardDecl();
+}
+
TypeIndex CodeViewDebug::lowerTypeClass(const DICompositeType *Ty) {
+ // Emit the complete type for unnamed structs. C++ classes with methods
+ // which have a circular reference back to the class type are expected to
+ // be named by the front-end and should not be "unnamed". C unnamed
+ // structs should not have circular references.
+ if (shouldAlwaysEmitCompleteClassType(Ty)) {
+ // If this unnamed complete type is already in the process of being defined
+ // then the description of the type is malformed and cannot be emitted
+ // into CodeView correctly so report a fatal error.
+ auto I = CompleteTypeIndices.find(Ty);
+ if (I != CompleteTypeIndices.end() && I->second == TypeIndex())
+ report_fatal_error("cannot debug circular reference to unnamed type");
+ return getCompleteTypeIndex(Ty);
+ }
+
// First, construct the forward decl. Don't look into Ty to compute the
// forward decl options, since it might not be available in all TUs.
TypeRecordKind Kind = getRecordKind(Ty);
@@ -1875,13 +2062,7 @@ TypeIndex CodeViewDebug::lowerCompleteTypeClass(const DICompositeType *Ty) {
SizeInBytes, FullName, Ty->getIdentifier());
TypeIndex ClassTI = TypeTable.writeLeafType(CR);
- if (const auto *File = Ty->getFile()) {
- StringIdRecord SIDR(TypeIndex(0x0), getFullFilepath(File));
- TypeIndex SIDI = TypeTable.writeLeafType(SIDR);
-
- UdtSourceLineRecord USLR(ClassTI, SIDI, Ty->getLine());
- TypeTable.writeLeafType(USLR);
- }
+ addUDTSrcLine(Ty, ClassTI);
addToUDTs(Ty);
@@ -1889,6 +2070,10 @@ TypeIndex CodeViewDebug::lowerCompleteTypeClass(const DICompositeType *Ty) {
}
TypeIndex CodeViewDebug::lowerTypeUnion(const DICompositeType *Ty) {
+ // Emit the complete type for unnamed unions.
+ if (shouldAlwaysEmitCompleteClassType(Ty))
+ return getCompleteTypeIndex(Ty);
+
ClassOptions CO =
ClassOptions::ForwardReference | getCommonClassOptions(Ty);
std::string FullName = getFullyQualifiedName(Ty);
@@ -1917,11 +2102,7 @@ TypeIndex CodeViewDebug::lowerCompleteTypeUnion(const DICompositeType *Ty) {
Ty->getIdentifier());
TypeIndex UnionTI = TypeTable.writeLeafType(UR);
- StringIdRecord SIR(TypeIndex(0x0), getFullFilepath(Ty->getFile()));
- TypeIndex SIRI = TypeTable.writeLeafType(SIR);
-
- UdtSourceLineRecord USLR(UnionTI, SIRI, Ty->getLine());
- TypeTable.writeLeafType(USLR);
+ addUDTSrcLine(Ty, UnionTI);
addToUDTs(Ty);
@@ -1943,8 +2124,7 @@ CodeViewDebug::lowerRecordFieldList(const DICompositeType *Ty) {
for (const DIDerivedType *I : Info.Inheritance) {
if (I->getFlags() & DINode::FlagVirtual) {
// Virtual base.
- // FIXME: Emit VBPtrOffset when the frontend provides it.
- unsigned VBPtrOffset = 0;
+ unsigned VBPtrOffset = I->getVBPtrOffset();
// FIXME: Despite the accessor name, the offset is really in bytes.
unsigned VBTableIndex = I->getOffsetInBits() / 4;
auto RecordKind = (I->getFlags() & DINode::FlagIndirectVirtualBase) == DINode::FlagIndirectVirtualBase
@@ -1956,6 +2136,7 @@ CodeViewDebug::lowerRecordFieldList(const DICompositeType *Ty) {
VBTableIndex);
ContinuationBuilder.writeMemberType(VBCR);
+ MemberCount++;
} else {
assert(I->getOffsetInBits() % 8 == 0 &&
"bases must be on byte boundaries");
@@ -1963,6 +2144,7 @@ CodeViewDebug::lowerRecordFieldList(const DICompositeType *Ty) {
getTypeIndex(I->getBaseType()),
I->getOffsetInBits() / 8);
ContinuationBuilder.writeMemberType(BCR);
+ MemberCount++;
}
}
@@ -2121,9 +2303,7 @@ TypeIndex CodeViewDebug::getCompleteTypeIndex(DITypeRef TypeRef) {
return getTypeIndex(Ty);
}
- // Check if we've already translated the complete record type. Lowering a
- // complete type should never trigger lowering another complete type, so we
- // can reuse the hash table lookup result.
+ // Check if we've already translated the complete record type.
const auto *CTy = cast<DICompositeType>(Ty);
auto InsertResult = CompleteTypeIndices.insert({CTy, TypeIndex()});
if (!InsertResult.second)
@@ -2134,13 +2314,16 @@ TypeIndex CodeViewDebug::getCompleteTypeIndex(DITypeRef TypeRef) {
// Make sure the forward declaration is emitted first. It's unclear if this
// is necessary, but MSVC does it, and we should follow suit until we can show
// otherwise.
- TypeIndex FwdDeclTI = getTypeIndex(CTy);
+ // We only emit a forward declaration for named types.
+ if (!CTy->getName().empty() || !CTy->getIdentifier().empty()) {
+ TypeIndex FwdDeclTI = getTypeIndex(CTy);
- // Just use the forward decl if we don't have complete type info. This might
- // happen if the frontend is using modules and expects the complete definition
- // to be emitted elsewhere.
- if (CTy->isForwardDecl())
- return FwdDeclTI;
+ // Just use the forward decl if we don't have complete type info. This
+ // might happen if the frontend is using modules and expects the complete
+ // definition to be emitted elsewhere.
+ if (CTy->isForwardDecl())
+ return FwdDeclTI;
+ }
TypeIndex TI;
switch (CTy->getTag()) {
@@ -2155,7 +2338,11 @@ TypeIndex CodeViewDebug::getCompleteTypeIndex(DITypeRef TypeRef) {
llvm_unreachable("not a record");
}
- InsertResult.first->second = TI;
+ // Update the type index associated with this CompositeType. This cannot
+ // use the 'InsertResult' iterator above because it is potentially
+ // invalidated by map insertions which can occur while lowering the class
+ // type above.
+ CompleteTypeIndices[CTy] = TI;
return TI;
}
@@ -2179,10 +2366,10 @@ void CodeViewDebug::emitLocalVariableList(ArrayRef<LocalVariable> Locals) {
for (const LocalVariable &L : Locals)
if (L.DIVar->isParameter())
Params.push_back(&L);
- std::sort(Params.begin(), Params.end(),
- [](const LocalVariable *L, const LocalVariable *R) {
- return L->DIVar->getArg() < R->DIVar->getArg();
- });
+ llvm::sort(Params.begin(), Params.end(),
+ [](const LocalVariable *L, const LocalVariable *R) {
+ return L->DIVar->getArg() < R->DIVar->getArg();
+ });
for (const LocalVariable *L : Params)
emitLocalVariable(*L);
@@ -2272,15 +2459,150 @@ void CodeViewDebug::emitLocalVariable(const LocalVariable &Var) {
}
}
+void CodeViewDebug::emitLexicalBlockList(ArrayRef<LexicalBlock *> Blocks,
+ const FunctionInfo& FI) {
+ for (LexicalBlock *Block : Blocks)
+ emitLexicalBlock(*Block, FI);
+}
+
+/// Emit an S_BLOCK32 and S_END record pair delimiting the contents of a
+/// lexical block scope.
+void CodeViewDebug::emitLexicalBlock(const LexicalBlock &Block,
+ const FunctionInfo& FI) {
+ MCSymbol *RecordBegin = MMI->getContext().createTempSymbol(),
+ *RecordEnd = MMI->getContext().createTempSymbol();
+
+ // Lexical block symbol record.
+ OS.AddComment("Record length");
+ OS.emitAbsoluteSymbolDiff(RecordEnd, RecordBegin, 2); // Record Length
+ OS.EmitLabel(RecordBegin);
+ OS.AddComment("Record kind: S_BLOCK32");
+ OS.EmitIntValue(SymbolKind::S_BLOCK32, 2); // Record Kind
+ OS.AddComment("PtrParent");
+ OS.EmitIntValue(0, 4); // PtrParent
+ OS.AddComment("PtrEnd");
+ OS.EmitIntValue(0, 4); // PtrEnd
+ OS.AddComment("Code size");
+ OS.emitAbsoluteSymbolDiff(Block.End, Block.Begin, 4); // Code Size
+ OS.AddComment("Function section relative address");
+ OS.EmitCOFFSecRel32(Block.Begin, /*Offset=*/0); // Func Offset
+ OS.AddComment("Function section index");
+ OS.EmitCOFFSectionIndex(FI.Begin); // Func Symbol
+ OS.AddComment("Lexical block name");
+ emitNullTerminatedSymbolName(OS, Block.Name); // Name
+ OS.EmitLabel(RecordEnd);
+
+ // Emit variables local to this lexical block.
+ emitLocalVariableList(Block.Locals);
+
+ // Emit lexical blocks contained within this block.
+ emitLexicalBlockList(Block.Children, FI);
+
+ // Close the lexical block scope.
+ OS.AddComment("Record length");
+ OS.EmitIntValue(2, 2); // Record Length
+ OS.AddComment("Record kind: S_END");
+ OS.EmitIntValue(SymbolKind::S_END, 2); // Record Kind
+}
+
+/// Convenience routine for collecting lexical block information for a list
+/// of lexical scopes.
+void CodeViewDebug::collectLexicalBlockInfo(
+ SmallVectorImpl<LexicalScope *> &Scopes,
+ SmallVectorImpl<LexicalBlock *> &Blocks,
+ SmallVectorImpl<LocalVariable> &Locals) {
+ for (LexicalScope *Scope : Scopes)
+ collectLexicalBlockInfo(*Scope, Blocks, Locals);
+}
+
+/// Populate the lexical blocks and local variable lists of the parent with
+/// information about the specified lexical scope.
+void CodeViewDebug::collectLexicalBlockInfo(
+ LexicalScope &Scope,
+ SmallVectorImpl<LexicalBlock *> &ParentBlocks,
+ SmallVectorImpl<LocalVariable> &ParentLocals) {
+ if (Scope.isAbstractScope())
+ return;
+
+ auto LocalsIter = ScopeVariables.find(&Scope);
+ if (LocalsIter == ScopeVariables.end()) {
+ // This scope does not contain variables and can be eliminated.
+ collectLexicalBlockInfo(Scope.getChildren(), ParentBlocks, ParentLocals);
+ return;
+ }
+ SmallVectorImpl<LocalVariable> &Locals = LocalsIter->second;
+
+ const DILexicalBlock *DILB = dyn_cast<DILexicalBlock>(Scope.getScopeNode());
+ if (!DILB) {
+ // This scope is not a lexical block and can be eliminated, but keep any
+ // local variables it contains.
+ ParentLocals.append(Locals.begin(), Locals.end());
+ collectLexicalBlockInfo(Scope.getChildren(), ParentBlocks, ParentLocals);
+ return;
+ }
+
+ const SmallVectorImpl<InsnRange> &Ranges = Scope.getRanges();
+ if (Ranges.size() != 1 || !getLabelAfterInsn(Ranges.front().second)) {
+ // This lexical block scope has too many address ranges to represent in the
+ // current CodeView format or does not have a valid address range.
+ // Eliminate this lexical scope and promote any locals it contains to the
+ // parent scope.
+ //
+ // For lexical scopes with multiple address ranges you may be tempted to
+ // construct a single range covering every instruction where the block is
+ // live and everything in between. Unfortunately, Visual Studio only
+ // displays variables from the first matching lexical block scope. If the
+ // first lexical block contains exception handling code or cold code which
+ // is moved to the bottom of the routine creating a single range covering
+ // nearly the entire routine, then it will hide all other lexical blocks
+ // and the variables they contain.
+ //
+ ParentLocals.append(Locals.begin(), Locals.end());
+ collectLexicalBlockInfo(Scope.getChildren(), ParentBlocks, ParentLocals);
+ return;
+ }
+
+ // Create a new CodeView lexical block for this lexical scope. If we've
+ // seen this DILexicalBlock before then the scope tree is malformed and
+ // we can handle this gracefully by not processing it a second time.
+ auto BlockInsertion = CurFn->LexicalBlocks.insert({DILB, LexicalBlock()});
+ if (!BlockInsertion.second)
+ return;
+
+ // Create a lexical block containing the local variables and collect the
+ // the lexical block information for the children.
+ const InsnRange &Range = Ranges.front();
+ assert(Range.first && Range.second);
+ LexicalBlock &Block = BlockInsertion.first->second;
+ Block.Begin = getLabelBeforeInsn(Range.first);
+ Block.End = getLabelAfterInsn(Range.second);
+ assert(Block.Begin && "missing label for scope begin");
+ assert(Block.End && "missing label for scope end");
+ Block.Name = DILB->getName();
+ Block.Locals = std::move(Locals);
+ ParentBlocks.push_back(&Block);
+ collectLexicalBlockInfo(Scope.getChildren(), Block.Children, Block.Locals);
+}
+
void CodeViewDebug::endFunctionImpl(const MachineFunction *MF) {
const Function &GV = MF->getFunction();
assert(FnDebugInfo.count(&GV));
- assert(CurFn == &FnDebugInfo[&GV]);
+ assert(CurFn == FnDebugInfo[&GV].get());
collectVariableInfo(GV.getSubprogram());
+ // Build the lexical block structure to emit for this routine.
+ if (LexicalScope *CFS = LScopes.getCurrentFunctionScope())
+ collectLexicalBlockInfo(*CFS, CurFn->ChildBlocks, CurFn->Locals);
+
+ // Clear the scope and variable information from the map which will not be
+ // valid after we have finished processing this routine. This also prepares
+ // the map for the subsequent routine.
+ ScopeVariables.clear();
+
// Don't emit anything if we don't have any line tables.
- if (!CurFn->HaveLineInfo) {
+ // Thunks are compiler-generated and probably won't have source correlation.
+ if (!CurFn->HaveLineInfo && !GV.getSubprogram()->isThunk()) {
FnDebugInfo.erase(&GV);
CurFn = nullptr;
return;
@@ -2296,8 +2618,8 @@ void CodeViewDebug::endFunctionImpl(const MachineFunction *MF) {
void CodeViewDebug::beginInstruction(const MachineInstr *MI) {
DebugHandlerBase::beginInstruction(MI);
- // Ignore DBG_VALUE locations and function prologue.
- if (!Asm || !CurFn || MI->isDebugValue() ||
+ // Ignore DBG_VALUE and DBG_LABEL locations and function prologue.
+ if (!Asm || !CurFn || MI->isDebugInstr() ||
MI->getFlag(MachineInstr::FrameSetup))
return;
@@ -2306,7 +2628,7 @@ void CodeViewDebug::beginInstruction(const MachineInstr *MI) {
DebugLoc DL = MI->getDebugLoc();
if (!DL && MI->getParent() != PrevInstBB) {
for (const auto &NextMI : *MI->getParent()) {
- if (NextMI.isDebugValue())
+ if (NextMI.isDebugInstr())
continue;
DL = NextMI.getDebugLoc();
if (DL)
@@ -2432,6 +2754,7 @@ void CodeViewDebug::emitDebugInfoForGlobal(const DIGlobalVariable *DIGV,
// FIXME: Thread local data, etc
MCSymbol *DataBegin = MMI->getContext().createTempSymbol(),
*DataEnd = MMI->getContext().createTempSymbol();
+ const unsigned FixedLengthOfThisRecord = 12;
OS.AddComment("Record length");
OS.emitAbsoluteSymbolDiff(DataEnd, DataBegin, 2);
OS.EmitLabel(DataBegin);
@@ -2459,6 +2782,6 @@ void CodeViewDebug::emitDebugInfoForGlobal(const DIGlobalVariable *DIGV,
OS.AddComment("Segment");
OS.EmitCOFFSectionIndex(GVSym);
OS.AddComment("Name");
- emitNullTerminatedSymbolName(OS, DIGV->getName());
+ emitNullTerminatedSymbolName(OS, DIGV->getName(), FixedLengthOfThisRecord);
OS.EmitLabel(DataEnd);
}
diff --git a/lib/CodeGen/AsmPrinter/CodeViewDebug.h b/lib/CodeGen/AsmPrinter/CodeViewDebug.h
index 69e93640d7ef..6a0da5f993d0 100644
--- a/lib/CodeGen/AsmPrinter/CodeViewDebug.h
+++ b/lib/CodeGen/AsmPrinter/CodeViewDebug.h
@@ -48,7 +48,7 @@ class MCStreamer;
class MCSymbol;
class MachineFunction;
-/// \brief Collects and handles line tables information in a CodeView format.
+/// Collects and handles line tables information in a CodeView format.
class LLVM_LIBRARY_VISIBILITY CodeViewDebug : public DebugHandlerBase {
MCStreamer &OS;
BumpPtrAllocator Allocator;
@@ -107,9 +107,23 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDebug : public DebugHandlerBase {
unsigned SiteFuncId = 0;
};
+ // Combines information from DILexicalBlock and LexicalScope.
+ struct LexicalBlock {
+ SmallVector<LocalVariable, 1> Locals;
+ SmallVector<LexicalBlock *, 1> Children;
+ const MCSymbol *Begin;
+ const MCSymbol *End;
+ StringRef Name;
+ };
+
// For each function, store a vector of labels to its instructions, as well as
// to the end of the function.
struct FunctionInfo {
+ FunctionInfo() = default;
+
+ // Uncopyable.
+ FunctionInfo(const FunctionInfo &FI) = delete;
+
/// Map from inlined call site to inlined instructions and child inlined
/// call sites. Listed in program order.
std::unordered_map<const DILocation *, InlineSite> InlineSites;
@@ -119,6 +133,11 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDebug : public DebugHandlerBase {
SmallVector<LocalVariable, 1> Locals;
+ std::unordered_map<const DILexicalBlockBase*, LexicalBlock> LexicalBlocks;
+
+ // Lexical blocks containing local variables.
+ SmallVector<LexicalBlock *, 1> ChildBlocks;
+
std::vector<std::pair<MCSymbol *, MDNode *>> Annotations;
const MCSymbol *Begin = nullptr;
@@ -129,6 +148,12 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDebug : public DebugHandlerBase {
};
FunctionInfo *CurFn = nullptr;
+ // Map used to seperate variables according to the lexical scope they belong
+ // in. This is populated by recordLocalVariable() before
+ // collectLexicalBlocks() separates the variables between the FunctionInfo
+ // and LexicalBlocks.
+ DenseMap<const LexicalScope *, SmallVector<LocalVariable, 1>> ScopeVariables;
+
/// The set of comdat .debug$S sections that we've seen so far. Each section
/// must start with a magic version number that must only be emitted once.
/// This set tracks which sections we've already opened.
@@ -159,7 +184,7 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDebug : public DebugHandlerBase {
/// Remember some debug info about each function. Keep it in a stable order to
/// emit at the end of the TU.
- MapVector<const Function *, FunctionInfo> FnDebugInfo;
+ MapVector<const Function *, std::unique_ptr<FunctionInfo>> FnDebugInfo;
/// Map from full file path to .cv_file id. Full paths are built from DIFiles
/// and are stored in FileToFilepathMap;
@@ -200,7 +225,7 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDebug : public DebugHandlerBase {
using FileToFilepathMapTy = std::map<const DIFile *, std::string>;
FileToFilepathMapTy FileToFilepathMap;
- StringRef getFullFilepath(const DIFile *S);
+ StringRef getFullFilepath(const DIFile *File);
unsigned maybeRecordFile(const DIFile *F);
@@ -214,7 +239,8 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDebug : public DebugHandlerBase {
}
/// Emit the magic version number at the start of a CodeView type or symbol
- /// section. Appears at the front of every .debug$S or .debug$T section.
+ /// section. Appears at the front of every .debug$S or .debug$T or .debug$P
+ /// section.
void emitCodeViewMagicVersion();
void emitTypeInformation();
@@ -225,6 +251,10 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDebug : public DebugHandlerBase {
void emitInlineeLinesSubsection();
+ void emitDebugInfoForThunk(const Function *GV,
+ FunctionInfo &FI,
+ const MCSymbol *Fn);
+
void emitDebugInfoForFunction(const Function *GV, FunctionInfo &FI);
void emitDebugInfoForGlobals();
@@ -253,9 +283,18 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDebug : public DebugHandlerBase {
void collectVariableInfoFromMFTable(DenseSet<InlinedVariable> &Processed);
+ // Construct the lexical block tree for a routine, pruning emptpy lexical
+ // scopes, and populate it with local variables.
+ void collectLexicalBlockInfo(SmallVectorImpl<LexicalScope *> &Scopes,
+ SmallVectorImpl<LexicalBlock *> &Blocks,
+ SmallVectorImpl<LocalVariable> &Locals);
+ void collectLexicalBlockInfo(LexicalScope &Scope,
+ SmallVectorImpl<LexicalBlock *> &ParentBlocks,
+ SmallVectorImpl<LocalVariable> &ParentLocals);
+
/// Records information about a local variable in the appropriate scope. In
/// particular, locals from inlined code live inside the inlining site.
- void recordLocalVariable(LocalVariable &&Var, const DILocation *Loc);
+ void recordLocalVariable(LocalVariable &&Var, const LexicalScope *LS);
/// Emits local variables in the appropriate order.
void emitLocalVariableList(ArrayRef<LocalVariable> Locals);
@@ -263,6 +302,13 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDebug : public DebugHandlerBase {
/// Emits an S_LOCAL record and its associated defined ranges.
void emitLocalVariable(const LocalVariable &Var);
+ /// Emits a sequence of lexical block scopes and their children.
+ void emitLexicalBlockList(ArrayRef<LexicalBlock *> Blocks,
+ const FunctionInfo& FI);
+
+ /// Emit a lexical block scope and its children.
+ void emitLexicalBlock(const LexicalBlock &Block, const FunctionInfo& FI);
+
/// Translates the DIType to codeview if necessary and returns a type index
/// for it.
codeview::TypeIndex getTypeIndex(DITypeRef TypeRef,
@@ -279,12 +325,18 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDebug : public DebugHandlerBase {
void addToUDTs(const DIType *Ty);
+ void addUDTSrcLine(const DIType *Ty, codeview::TypeIndex TI);
+
codeview::TypeIndex lowerType(const DIType *Ty, const DIType *ClassTy);
codeview::TypeIndex lowerTypeAlias(const DIDerivedType *Ty);
codeview::TypeIndex lowerTypeArray(const DICompositeType *Ty);
codeview::TypeIndex lowerTypeBasic(const DIBasicType *Ty);
- codeview::TypeIndex lowerTypePointer(const DIDerivedType *Ty);
- codeview::TypeIndex lowerTypeMemberPointer(const DIDerivedType *Ty);
+ codeview::TypeIndex lowerTypePointer(
+ const DIDerivedType *Ty,
+ codeview::PointerOptions PO = codeview::PointerOptions::None);
+ codeview::TypeIndex lowerTypeMemberPointer(
+ const DIDerivedType *Ty,
+ codeview::PointerOptions PO = codeview::PointerOptions::None);
codeview::TypeIndex lowerTypeModifier(const DIDerivedType *Ty);
codeview::TypeIndex lowerTypeFunction(const DISubroutineType *Ty);
codeview::TypeIndex lowerTypeVFTableShape(const DIDerivedType *Ty);
@@ -327,21 +379,21 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDebug : public DebugHandlerBase {
unsigned getPointerSizeInBytes();
protected:
- /// \brief Gather pre-function debug information.
+ /// Gather pre-function debug information.
void beginFunctionImpl(const MachineFunction *MF) override;
- /// \brief Gather post-function debug information.
+ /// Gather post-function debug information.
void endFunctionImpl(const MachineFunction *) override;
public:
- CodeViewDebug(AsmPrinter *Asm);
+ CodeViewDebug(AsmPrinter *AP);
void setSymbolSize(const MCSymbol *, uint64_t) override {}
- /// \brief Emit the COFF section that holds the line table information.
+ /// Emit the COFF section that holds the line table information.
void endModule() override;
- /// \brief Process beginning of an instruction.
+ /// Process beginning of an instruction.
void beginInstruction(const MachineInstr *MI) override;
};
diff --git a/lib/CodeGen/AsmPrinter/DIE.cpp b/lib/CodeGen/AsmPrinter/DIE.cpp
index b3148db30cd6..570424a79c81 100644
--- a/lib/CodeGen/AsmPrinter/DIE.cpp
+++ b/lib/CodeGen/AsmPrinter/DIE.cpp
@@ -17,6 +17,7 @@
#include "DwarfUnit.h"
#include "llvm/ADT/Twine.h"
#include "llvm/CodeGen/AsmPrinter.h"
+#include "llvm/Config/llvm-config.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCContext.h"
@@ -86,8 +87,9 @@ void DIEAbbrev::Emit(const AsmPrinter *AP) const {
// easily, which helps track down where it came from.
if (!dwarf::isValidFormForVersion(AttrData.getForm(),
AP->getDwarfVersion())) {
- DEBUG(dbgs() << "Invalid form " << format("0x%x", AttrData.getForm())
- << " for DWARF version " << AP->getDwarfVersion() << "\n");
+ LLVM_DEBUG(dbgs() << "Invalid form " << format("0x%x", AttrData.getForm())
+ << " for DWARF version " << AP->getDwarfVersion()
+ << "\n");
llvm_unreachable("Invalid form for specified DWARF version");
}
#endif
@@ -388,6 +390,7 @@ void DIEInteger::EmitValue(const AsmPrinter *Asm, dwarf::Form Form) const {
case dwarf::DW_FORM_data2:
case dwarf::DW_FORM_strx2:
case dwarf::DW_FORM_addrx2:
+ case dwarf::DW_FORM_strx3:
case dwarf::DW_FORM_strp:
case dwarf::DW_FORM_ref4:
case dwarf::DW_FORM_data4:
@@ -410,6 +413,7 @@ void DIEInteger::EmitValue(const AsmPrinter *Asm, dwarf::Form Form) const {
case dwarf::DW_FORM_GNU_str_index:
case dwarf::DW_FORM_GNU_addr_index:
case dwarf::DW_FORM_ref_udata:
+ case dwarf::DW_FORM_strx:
case dwarf::DW_FORM_udata:
Asm->EmitULEB128(Integer);
return;
@@ -423,58 +427,23 @@ void DIEInteger::EmitValue(const AsmPrinter *Asm, dwarf::Form Form) const {
/// SizeOf - Determine size of integer value in bytes.
///
unsigned DIEInteger::SizeOf(const AsmPrinter *AP, dwarf::Form Form) const {
+ dwarf::FormParams Params = {0, 0, dwarf::DWARF32};
+ if (AP)
+ Params = {AP->getDwarfVersion(), uint8_t(AP->getPointerSize()),
+ AP->OutStreamer->getContext().getDwarfFormat()};
+
+ if (Optional<uint8_t> FixedSize = dwarf::getFixedFormByteSize(Form, Params))
+ return *FixedSize;
+
switch (Form) {
- case dwarf::DW_FORM_implicit_const:
- case dwarf::DW_FORM_flag_present:
- return 0;
- case dwarf::DW_FORM_flag:
- case dwarf::DW_FORM_ref1:
- case dwarf::DW_FORM_data1:
- case dwarf::DW_FORM_strx1:
- case dwarf::DW_FORM_addrx1:
- return sizeof(int8_t);
- case dwarf::DW_FORM_ref2:
- case dwarf::DW_FORM_data2:
- case dwarf::DW_FORM_strx2:
- case dwarf::DW_FORM_addrx2:
- return sizeof(int16_t);
- case dwarf::DW_FORM_ref4:
- case dwarf::DW_FORM_data4:
- case dwarf::DW_FORM_ref_sup4:
- case dwarf::DW_FORM_strx4:
- case dwarf::DW_FORM_addrx4:
- return sizeof(int32_t);
- case dwarf::DW_FORM_ref8:
- case dwarf::DW_FORM_ref_sig8:
- case dwarf::DW_FORM_data8:
- case dwarf::DW_FORM_ref_sup8:
- return sizeof(int64_t);
- case dwarf::DW_FORM_ref_addr:
- if (AP->getDwarfVersion() == 2)
- return AP->getPointerSize();
- LLVM_FALLTHROUGH;
- case dwarf::DW_FORM_strp:
- case dwarf::DW_FORM_GNU_ref_alt:
- case dwarf::DW_FORM_GNU_strp_alt:
- case dwarf::DW_FORM_line_strp:
- case dwarf::DW_FORM_sec_offset:
- case dwarf::DW_FORM_strp_sup:
- switch (AP->OutStreamer->getContext().getDwarfFormat()) {
- case dwarf::DWARF32:
- return 4;
- case dwarf::DWARF64:
- return 8;
- }
- llvm_unreachable("Invalid DWARF format");
case dwarf::DW_FORM_GNU_str_index:
case dwarf::DW_FORM_GNU_addr_index:
case dwarf::DW_FORM_ref_udata:
+ case dwarf::DW_FORM_strx:
case dwarf::DW_FORM_udata:
return getULEB128Size(Integer);
case dwarf::DW_FORM_sdata:
return getSLEB128Size(Integer);
- case dwarf::DW_FORM_addr:
- return AP->getPointerSize();
default: llvm_unreachable("DIE Value form not supported yet");
}
}
@@ -564,44 +533,46 @@ void DIEDelta::print(raw_ostream &O) const {
/// EmitValue - Emit string value.
///
void DIEString::EmitValue(const AsmPrinter *AP, dwarf::Form Form) const {
- assert(
- (Form == dwarf::DW_FORM_strp || Form == dwarf::DW_FORM_GNU_str_index) &&
- "Expected valid string form");
-
// Index of string in symbol table.
- if (Form == dwarf::DW_FORM_GNU_str_index) {
+ switch (Form) {
+ case dwarf::DW_FORM_GNU_str_index:
+ case dwarf::DW_FORM_strx:
+ case dwarf::DW_FORM_strx1:
+ case dwarf::DW_FORM_strx2:
+ case dwarf::DW_FORM_strx3:
+ case dwarf::DW_FORM_strx4:
DIEInteger(S.getIndex()).EmitValue(AP, Form);
return;
- }
-
- // Relocatable symbol.
- assert(Form == dwarf::DW_FORM_strp);
- if (AP->MAI->doesDwarfUseRelocationsAcrossSections()) {
- DIELabel(S.getSymbol()).EmitValue(AP, Form);
+ case dwarf::DW_FORM_strp:
+ if (AP->MAI->doesDwarfUseRelocationsAcrossSections())
+ DIELabel(S.getSymbol()).EmitValue(AP, Form);
+ else
+ DIEInteger(S.getOffset()).EmitValue(AP, Form);
return;
+ default:
+ llvm_unreachable("Expected valid string form");
}
-
- // Offset into symbol table.
- DIEInteger(S.getOffset()).EmitValue(AP, Form);
}
/// SizeOf - Determine size of delta value in bytes.
///
unsigned DIEString::SizeOf(const AsmPrinter *AP, dwarf::Form Form) const {
- assert(
- (Form == dwarf::DW_FORM_strp || Form == dwarf::DW_FORM_GNU_str_index) &&
- "Expected valid string form");
-
// Index of string in symbol table.
- if (Form == dwarf::DW_FORM_GNU_str_index)
+ switch (Form) {
+ case dwarf::DW_FORM_GNU_str_index:
+ case dwarf::DW_FORM_strx:
+ case dwarf::DW_FORM_strx1:
+ case dwarf::DW_FORM_strx2:
+ case dwarf::DW_FORM_strx3:
+ case dwarf::DW_FORM_strx4:
return DIEInteger(S.getIndex()).SizeOf(AP, Form);
-
- // Relocatable symbol.
- if (AP->MAI->doesDwarfUseRelocationsAcrossSections())
- return DIELabel(S.getSymbol()).SizeOf(AP, Form);
-
- // Offset into symbol table.
- return DIEInteger(S.getOffset()).SizeOf(AP, Form);
+ case dwarf::DW_FORM_strp:
+ if (AP->MAI->doesDwarfUseRelocationsAcrossSections())
+ return DIELabel(S.getSymbol()).SizeOf(AP, Form);
+ return DIEInteger(S.getOffset()).SizeOf(AP, Form);
+ default:
+ llvm_unreachable("Expected valid string form");
+ }
}
LLVM_DUMP_METHOD
@@ -615,8 +586,8 @@ void DIEString::print(raw_ostream &O) const {
void DIEInlineString::EmitValue(const AsmPrinter *AP, dwarf::Form Form) const {
if (Form == dwarf::DW_FORM_string) {
for (char ch : S)
- AP->EmitInt8(ch);
- AP->EmitInt8(0);
+ AP->emitInt8(ch);
+ AP->emitInt8(0);
return;
}
llvm_unreachable("Expected valid string form");
@@ -722,9 +693,9 @@ unsigned DIELoc::ComputeSize(const AsmPrinter *AP) const {
void DIELoc::EmitValue(const AsmPrinter *Asm, dwarf::Form Form) const {
switch (Form) {
default: llvm_unreachable("Improper form for block");
- case dwarf::DW_FORM_block1: Asm->EmitInt8(Size); break;
- case dwarf::DW_FORM_block2: Asm->EmitInt16(Size); break;
- case dwarf::DW_FORM_block4: Asm->EmitInt32(Size); break;
+ case dwarf::DW_FORM_block1: Asm->emitInt8(Size); break;
+ case dwarf::DW_FORM_block2: Asm->emitInt16(Size); break;
+ case dwarf::DW_FORM_block4: Asm->emitInt32(Size); break;
case dwarf::DW_FORM_block:
case dwarf::DW_FORM_exprloc:
Asm->EmitULEB128(Size); break;
@@ -773,10 +744,11 @@ unsigned DIEBlock::ComputeSize(const AsmPrinter *AP) const {
void DIEBlock::EmitValue(const AsmPrinter *Asm, dwarf::Form Form) const {
switch (Form) {
default: llvm_unreachable("Improper form for block");
- case dwarf::DW_FORM_block1: Asm->EmitInt8(Size); break;
- case dwarf::DW_FORM_block2: Asm->EmitInt16(Size); break;
- case dwarf::DW_FORM_block4: Asm->EmitInt32(Size); break;
+ case dwarf::DW_FORM_block1: Asm->emitInt8(Size); break;
+ case dwarf::DW_FORM_block2: Asm->emitInt16(Size); break;
+ case dwarf::DW_FORM_block4: Asm->emitInt32(Size); break;
case dwarf::DW_FORM_block: Asm->EmitULEB128(Size); break;
+ case dwarf::DW_FORM_string: break;
case dwarf::DW_FORM_data16: break;
}
diff --git a/lib/CodeGen/AsmPrinter/DIEHash.cpp b/lib/CodeGen/AsmPrinter/DIEHash.cpp
index 15ade3c96dfe..b8f1202494d7 100644
--- a/lib/CodeGen/AsmPrinter/DIEHash.cpp
+++ b/lib/CodeGen/AsmPrinter/DIEHash.cpp
@@ -28,7 +28,7 @@ using namespace llvm;
#define DEBUG_TYPE "dwarfdebug"
-/// \brief Grabs the string in whichever attribute is passed in and returns
+/// Grabs the string in whichever attribute is passed in and returns
/// a reference to it.
static StringRef getDIEStringAttr(const DIE &Die, uint16_t Attr) {
// Iterate through all the attributes until we find the one we're
@@ -40,10 +40,10 @@ static StringRef getDIEStringAttr(const DIE &Die, uint16_t Attr) {
return StringRef("");
}
-/// \brief Adds the string in \p Str to the hash. This also hashes
+/// Adds the string in \p Str to the hash. This also hashes
/// a trailing NULL with the string.
void DIEHash::addString(StringRef Str) {
- DEBUG(dbgs() << "Adding string " << Str << " to hash.\n");
+ LLVM_DEBUG(dbgs() << "Adding string " << Str << " to hash.\n");
Hash.update(Str);
Hash.update(makeArrayRef((uint8_t)'\0'));
}
@@ -51,9 +51,9 @@ void DIEHash::addString(StringRef Str) {
// FIXME: The LEB128 routines are copied and only slightly modified out of
// LEB128.h.
-/// \brief Adds the unsigned in \p Value to the hash encoded as a ULEB128.
+/// Adds the unsigned in \p Value to the hash encoded as a ULEB128.
void DIEHash::addULEB128(uint64_t Value) {
- DEBUG(dbgs() << "Adding ULEB128 " << Value << " to hash.\n");
+ LLVM_DEBUG(dbgs() << "Adding ULEB128 " << Value << " to hash.\n");
do {
uint8_t Byte = Value & 0x7f;
Value >>= 7;
@@ -64,7 +64,7 @@ void DIEHash::addULEB128(uint64_t Value) {
}
void DIEHash::addSLEB128(int64_t Value) {
- DEBUG(dbgs() << "Adding ULEB128 " << Value << " to hash.\n");
+ LLVM_DEBUG(dbgs() << "Adding ULEB128 " << Value << " to hash.\n");
bool More;
do {
uint8_t Byte = Value & 0x7f;
@@ -77,10 +77,10 @@ void DIEHash::addSLEB128(int64_t Value) {
} while (More);
}
-/// \brief Including \p Parent adds the context of Parent to the hash..
+/// Including \p Parent adds the context of Parent to the hash..
void DIEHash::addParentContext(const DIE &Parent) {
- DEBUG(dbgs() << "Adding parent context to hash...\n");
+ LLVM_DEBUG(dbgs() << "Adding parent context to hash...\n");
// [7.27.2] For each surrounding type or namespace beginning with the
// outermost such construct...
@@ -108,7 +108,7 @@ void DIEHash::addParentContext(const DIE &Parent) {
// ... Then the name, taken from the DW_AT_name attribute.
StringRef Name = getDIEStringAttr(Die, dwarf::DW_AT_name);
- DEBUG(dbgs() << "... adding context: " << Name << "\n");
+ LLVM_DEBUG(dbgs() << "... adding context: " << Name << "\n");
if (!Name.empty())
addString(Name);
}
@@ -118,9 +118,9 @@ void DIEHash::addParentContext(const DIE &Parent) {
void DIEHash::collectAttributes(const DIE &Die, DIEAttrs &Attrs) {
for (const auto &V : Die.values()) {
- DEBUG(dbgs() << "Attribute: "
- << dwarf::AttributeString(V.getAttribute())
- << " added.\n");
+ LLVM_DEBUG(dbgs() << "Attribute: "
+ << dwarf::AttributeString(V.getAttribute())
+ << " added.\n");
switch (V.getAttribute()) {
#define HANDLE_DIE_HASH_ATTR(NAME) \
case dwarf::NAME: \
diff --git a/lib/CodeGen/AsmPrinter/DIEHash.h b/lib/CodeGen/AsmPrinter/DIEHash.h
index 29337ae38a99..dae517ab2c29 100644
--- a/lib/CodeGen/AsmPrinter/DIEHash.h
+++ b/lib/CodeGen/AsmPrinter/DIEHash.h
@@ -23,7 +23,7 @@ namespace llvm {
class AsmPrinter;
class CompileUnit;
-/// \brief An object containing the capability of hashing and adding hash
+/// An object containing the capability of hashing and adding hash
/// attributes onto a DIE.
class DIEHash {
// Collection of all attributes used in hashing a particular DIE.
@@ -35,66 +35,66 @@ class DIEHash {
public:
DIEHash(AsmPrinter *A = nullptr) : AP(A) {}
- /// \brief Computes the CU signature.
+ /// Computes the CU signature.
uint64_t computeCUSignature(StringRef DWOName, const DIE &Die);
- /// \brief Computes the type signature.
+ /// Computes the type signature.
uint64_t computeTypeSignature(const DIE &Die);
// Helper routines to process parts of a DIE.
private:
- /// \brief Adds the parent context of \param Die to the hash.
- void addParentContext(const DIE &Die);
+ /// Adds the parent context of \param Parent to the hash.
+ void addParentContext(const DIE &Parent);
- /// \brief Adds the attributes of \param Die to the hash.
+ /// Adds the attributes of \param Die to the hash.
void addAttributes(const DIE &Die);
- /// \brief Computes the full DWARF4 7.27 hash of the DIE.
+ /// Computes the full DWARF4 7.27 hash of the DIE.
void computeHash(const DIE &Die);
// Routines that add DIEValues to the hash.
public:
- /// \brief Adds \param Value to the hash.
+ /// Adds \param Value to the hash.
void update(uint8_t Value) { Hash.update(Value); }
- /// \brief Encodes and adds \param Value to the hash as a ULEB128.
+ /// Encodes and adds \param Value to the hash as a ULEB128.
void addULEB128(uint64_t Value);
- /// \brief Encodes and adds \param Value to the hash as a SLEB128.
+ /// Encodes and adds \param Value to the hash as a SLEB128.
void addSLEB128(int64_t Value);
private:
- /// \brief Adds \param Str to the hash and includes a NULL byte.
+ /// Adds \param Str to the hash and includes a NULL byte.
void addString(StringRef Str);
- /// \brief Collects the attributes of DIE \param Die into the \param Attrs
+ /// Collects the attributes of DIE \param Die into the \param Attrs
/// structure.
void collectAttributes(const DIE &Die, DIEAttrs &Attrs);
- /// \brief Hashes the attributes in \param Attrs in order.
+ /// Hashes the attributes in \param Attrs in order.
void hashAttributes(const DIEAttrs &Attrs, dwarf::Tag Tag);
- /// \brief Hashes the data in a block like DIEValue, e.g. DW_FORM_block or
+ /// Hashes the data in a block like DIEValue, e.g. DW_FORM_block or
/// DW_FORM_exprloc.
void hashBlockData(const DIE::const_value_range &Values);
- /// \brief Hashes the contents pointed to in the .debug_loc section.
+ /// Hashes the contents pointed to in the .debug_loc section.
void hashLocList(const DIELocList &LocList);
- /// \brief Hashes an individual attribute.
+ /// Hashes an individual attribute.
void hashAttribute(const DIEValue &Value, dwarf::Tag Tag);
- /// \brief Hashes an attribute that refers to another DIE.
+ /// Hashes an attribute that refers to another DIE.
void hashDIEEntry(dwarf::Attribute Attribute, dwarf::Tag Tag,
const DIE &Entry);
- /// \brief Hashes a reference to a named type in such a way that is
+ /// Hashes a reference to a named type in such a way that is
/// independent of whether that type is described by a declaration or a
/// definition.
void hashShallowTypeReference(dwarf::Attribute Attribute, const DIE &Entry,
StringRef Name);
- /// \brief Hashes a reference to a previously referenced type DIE.
+ /// Hashes a reference to a previously referenced type DIE.
void hashRepeatedTypeReference(dwarf::Attribute Attribute,
unsigned DieNumber);
diff --git a/lib/CodeGen/AsmPrinter/DbgValueHistoryCalculator.cpp b/lib/CodeGen/AsmPrinter/DbgValueHistoryCalculator.cpp
index 856758c8e4f6..25518a339c61 100644
--- a/lib/CodeGen/AsmPrinter/DbgValueHistoryCalculator.cpp
+++ b/lib/CodeGen/AsmPrinter/DbgValueHistoryCalculator.cpp
@@ -31,7 +31,7 @@ using namespace llvm;
#define DEBUG_TYPE "dwarfdebug"
-// \brief If @MI is a DBG_VALUE with debug value described by a
+// If @MI is a DBG_VALUE with debug value described by a
// defined register, returns the number of this register.
// In the other case, returns 0.
static unsigned isDescribedByReg(const MachineInstr &MI) {
@@ -50,8 +50,8 @@ void DbgValueHistoryMap::startInstrRange(InlinedVariable Var,
auto &Ranges = VarInstrRanges[Var];
if (!Ranges.empty() && Ranges.back().second == nullptr &&
Ranges.back().first->isIdenticalTo(MI)) {
- DEBUG(dbgs() << "Coalescing identical DBG_VALUE entries:\n"
- << "\t" << Ranges.back().first << "\t" << MI << "\n");
+ LLVM_DEBUG(dbgs() << "Coalescing identical DBG_VALUE entries:\n"
+ << "\t" << Ranges.back().first << "\t" << MI << "\n");
return;
}
Ranges.push_back(std::make_pair(&MI, nullptr));
@@ -86,7 +86,7 @@ using RegDescribedVarsMap = std::map<unsigned, SmallVector<InlinedVariable, 1>>;
} // end anonymous namespace
-// \brief Claim that @Var is not described by @RegNo anymore.
+// Claim that @Var is not described by @RegNo anymore.
static void dropRegDescribedVar(RegDescribedVarsMap &RegVars, unsigned RegNo,
InlinedVariable Var) {
const auto &I = RegVars.find(RegNo);
@@ -100,7 +100,7 @@ static void dropRegDescribedVar(RegDescribedVarsMap &RegVars, unsigned RegNo,
RegVars.erase(I);
}
-// \brief Claim that @Var is now described by @RegNo.
+// Claim that @Var is now described by @RegNo.
static void addRegDescribedVar(RegDescribedVarsMap &RegVars, unsigned RegNo,
InlinedVariable Var) {
assert(RegNo != 0U);
@@ -109,7 +109,7 @@ static void addRegDescribedVar(RegDescribedVarsMap &RegVars, unsigned RegNo,
VarSet.push_back(Var);
}
-// \brief Terminate the location range for variables described by register at
+// Terminate the location range for variables described by register at
// @I by inserting @ClobberingInstr to their history.
static void clobberRegisterUses(RegDescribedVarsMap &RegVars,
RegDescribedVarsMap::iterator I,
@@ -122,7 +122,7 @@ static void clobberRegisterUses(RegDescribedVarsMap &RegVars,
RegVars.erase(I);
}
-// \brief Terminate the location range for variables described by register
+// Terminate the location range for variables described by register
// @RegNo by inserting @ClobberingInstr to their history.
static void clobberRegisterUses(RegDescribedVarsMap &RegVars, unsigned RegNo,
DbgValueHistoryMap &HistMap,
@@ -133,7 +133,7 @@ static void clobberRegisterUses(RegDescribedVarsMap &RegVars, unsigned RegNo,
clobberRegisterUses(RegVars, I, HistMap, ClobberingInstr);
}
-// \brief Returns the first instruction in @MBB which corresponds to
+// Returns the first instruction in @MBB which corresponds to
// the function epilogue, or nullptr if @MBB doesn't contain an epilogue.
static const MachineInstr *getFirstEpilogueInst(const MachineBasicBlock &MBB) {
auto LastMI = MBB.getLastNonDebugInstr();
@@ -155,7 +155,7 @@ static const MachineInstr *getFirstEpilogueInst(const MachineBasicBlock &MBB) {
return &*MBB.begin();
}
-// \brief Collect registers that are modified in the function body (their
+// Collect registers that are modified in the function body (their
// contents is changed outside of the prologue and epilogue).
static void collectChangingRegs(const MachineFunction *MF,
const TargetRegisterInfo *TRI,
@@ -198,7 +198,7 @@ void llvm::calculateDbgValueHistory(const MachineFunction *MF,
RegDescribedVarsMap RegVars;
for (const auto &MBB : *MF) {
for (const auto &MI : MBB) {
- if (!MI.isDebugValue()) {
+ if (!MI.isDebugInstr()) {
// Not a DBG_VALUE instruction. It may clobber registers which describe
// some variables.
for (const MachineOperand &MO : MI.operands()) {
@@ -234,6 +234,10 @@ void llvm::calculateDbgValueHistory(const MachineFunction *MF,
continue;
}
+ // Skip DBG_LABEL instructions.
+ if (MI.isDebugLabel())
+ continue;
+
assert(MI.getNumOperands() > 1 && "Invalid DBG_VALUE instruction!");
// Use the base variable (without any DW_OP_piece expressions)
// as index into History. The full variables including the
@@ -265,3 +269,33 @@ void llvm::calculateDbgValueHistory(const MachineFunction *MF,
}
}
}
+
+#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
+LLVM_DUMP_METHOD void DbgValueHistoryMap::dump() const {
+ dbgs() << "DbgValueHistoryMap:\n";
+ for (const auto &VarRangePair : *this) {
+ const InlinedVariable &Var = VarRangePair.first;
+ const InstrRanges &Ranges = VarRangePair.second;
+
+ const DILocalVariable *LocalVar = Var.first;
+ const DILocation *Location = Var.second;
+
+ dbgs() << " - " << LocalVar->getName() << " at ";
+
+ if (Location)
+ dbgs() << Location->getFilename() << ":" << Location->getLine() << ":"
+ << Location->getColumn();
+ else
+ dbgs() << "<unknown location>";
+
+ dbgs() << " --\n";
+
+ for (const InstrRange &Range : Ranges) {
+ dbgs() << " Begin: " << *Range.first;
+ if (Range.second)
+ dbgs() << " End : " << *Range.second;
+ dbgs() << "\n";
+ }
+ }
+}
+#endif
diff --git a/lib/CodeGen/AsmPrinter/DbgValueHistoryCalculator.h b/lib/CodeGen/AsmPrinter/DbgValueHistoryCalculator.h
index a7b0562e8102..a262cb38b175 100644
--- a/lib/CodeGen/AsmPrinter/DbgValueHistoryCalculator.h
+++ b/lib/CodeGen/AsmPrinter/DbgValueHistoryCalculator.h
@@ -52,6 +52,10 @@ public:
void clear() { VarInstrRanges.clear(); }
InstrRangesMap::const_iterator begin() const { return VarInstrRanges.begin(); }
InstrRangesMap::const_iterator end() const { return VarInstrRanges.end(); }
+
+#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
+ LLVM_DUMP_METHOD void dump() const;
+#endif
};
void calculateDbgValueHistory(const MachineFunction *MF,
diff --git a/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp b/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp
index d94b0e5c2118..82e14dc13cb1 100644
--- a/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp
+++ b/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp
@@ -25,6 +25,8 @@
using namespace llvm;
+#define DEBUG_TYPE "dwarfdebug"
+
Optional<DbgVariableLocation>
DbgVariableLocation::extractFromMachineInstruction(
const MachineInstr &Instruction) {
@@ -123,29 +125,6 @@ MCSymbol *DebugHandlerBase::getLabelAfterInsn(const MachineInstr *MI) {
return LabelsAfterInsn.lookup(MI);
}
-int DebugHandlerBase::fragmentCmp(const DIExpression *P1,
- const DIExpression *P2) {
- auto Fragment1 = *P1->getFragmentInfo();
- auto Fragment2 = *P2->getFragmentInfo();
- unsigned l1 = Fragment1.OffsetInBits;
- unsigned l2 = Fragment2.OffsetInBits;
- unsigned r1 = l1 + Fragment1.SizeInBits;
- unsigned r2 = l2 + Fragment2.SizeInBits;
- if (r1 <= l2)
- return -1;
- else if (r2 <= l1)
- return 1;
- else
- return 0;
-}
-
-bool DebugHandlerBase::fragmentsOverlap(const DIExpression *P1,
- const DIExpression *P2) {
- if (!P1->isFragment() || !P2->isFragment())
- return true;
- return fragmentCmp(P1, P2) == 0;
-}
-
/// If this type is derived from a base type then return base type size.
uint64_t DebugHandlerBase::getBaseTypeSize(const DITypeRef TyRef) {
DIType *Ty = TyRef.resolve();
@@ -163,7 +142,8 @@ uint64_t DebugHandlerBase::getBaseTypeSize(const DITypeRef TyRef) {
DIType *BaseType = DDTy->getBaseType().resolve();
- assert(BaseType && "Unexpected invalid base type");
+ if (!BaseType)
+ return 0;
// If this is a derived type, go ahead and get the base type, unless it's a
// reference then it's just the size of the field. Pointer types have no need
@@ -212,6 +192,7 @@ void DebugHandlerBase::beginFunction(const MachineFunction *MF) {
assert(DbgValues.empty() && "DbgValues map wasn't cleaned!");
calculateDbgValueHistory(MF, Asm->MF->getSubtarget().getRegisterInfo(),
DbgValues);
+ LLVM_DEBUG(DbgValues.dump());
// Request labels for the full history.
for (const auto &I : DbgValues) {
@@ -231,8 +212,8 @@ void DebugHandlerBase::beginFunction(const MachineFunction *MF) {
const DIExpression *Fragment = I->first->getDebugExpression();
if (std::all_of(Ranges.begin(), I,
[&](DbgValueHistoryMap::InstrRange Pred) {
- return !fragmentsOverlap(
- Fragment, Pred.first->getDebugExpression());
+ return !Fragment->fragmentsOverlap(
+ Pred.first->getDebugExpression());
}))
LabelsBeforeInsn[I->first] = Asm->getFunctionBegin();
else
diff --git a/lib/CodeGen/AsmPrinter/DebugHandlerBase.h b/lib/CodeGen/AsmPrinter/DebugHandlerBase.h
index 245d70038de9..1ccefe32be75 100644
--- a/lib/CodeGen/AsmPrinter/DebugHandlerBase.h
+++ b/lib/CodeGen/AsmPrinter/DebugHandlerBase.h
@@ -122,14 +122,6 @@ public:
/// Return Label immediately following the instruction.
MCSymbol *getLabelAfterInsn(const MachineInstr *MI);
- /// Determine the relative position of the fragments described by P1 and P2.
- /// Returns -1 if P1 is entirely before P2, 0 if P1 and P2 overlap, 1 if P1 is
- /// entirely after P2.
- static int fragmentCmp(const DIExpression *P1, const DIExpression *P2);
-
- /// Determine whether two variable fragments overlap.
- static bool fragmentsOverlap(const DIExpression *P1, const DIExpression *P2);
-
/// If this type is derived from a base type then return base type size.
static uint64_t getBaseTypeSize(const DITypeRef TyRef);
};
diff --git a/lib/CodeGen/AsmPrinter/DebugLocEntry.h b/lib/CodeGen/AsmPrinter/DebugLocEntry.h
index 3d6d8a76529c..ac49657b68fa 100644
--- a/lib/CodeGen/AsmPrinter/DebugLocEntry.h
+++ b/lib/CodeGen/AsmPrinter/DebugLocEntry.h
@@ -11,6 +11,7 @@
#define LLVM_LIB_CODEGEN_ASMPRINTER_DEBUGLOCENTRY_H
#include "DebugLocStream.h"
+#include "llvm/Config/llvm-config.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DebugInfo.h"
#include "llvm/MC/MCSymbol.h"
@@ -20,7 +21,7 @@
namespace llvm {
class AsmPrinter;
-/// \brief This struct describes location entries emitted in the .debug_loc
+/// This struct describes location entries emitted in the .debug_loc
/// section.
class DebugLocEntry {
/// Begin and end symbols for the address range that this location is valid.
@@ -28,7 +29,7 @@ class DebugLocEntry {
const MCSymbol *End;
public:
- /// \brief A single location or constant.
+ /// A single location or constant.
struct Value {
Value(const DIExpression *Expr, int64_t i)
: Expression(Expr), EntryKind(E_Integer) {
@@ -105,13 +106,13 @@ public:
Values.push_back(std::move(Val));
}
- /// \brief If this and Next are describing different pieces of the same
+ /// If this and Next are describing different pieces of the same
/// variable, merge them by appending Next's values to the current
/// list of values.
/// Return true if the merge was successful.
bool MergeValues(const DebugLocEntry &Next);
- /// \brief Attempt to merge this DebugLocEntry with Next and return
+ /// Attempt to merge this DebugLocEntry with Next and return
/// true if the merge was successful. Entries can be merged if they
/// share the same Loc/Constant and if Next immediately follows this
/// Entry.
@@ -135,10 +136,10 @@ public:
}) && "value must be a piece");
}
- // \brief Sort the pieces by offset.
+ // Sort the pieces by offset.
// Remove any duplicate entries by dropping all but the first.
void sortUniqueValues() {
- std::sort(Values.begin(), Values.end());
+ llvm::sort(Values.begin(), Values.end());
Values.erase(
std::unique(
Values.begin(), Values.end(), [](const Value &A, const Value &B) {
@@ -147,12 +148,12 @@ public:
Values.end());
}
- /// \brief Lower this entry into a DWARF expression.
+ /// Lower this entry into a DWARF expression.
void finalize(const AsmPrinter &AP, DebugLocStream::ListBuilder &List,
const DIBasicType *BT);
};
-/// \brief Compare two Values for equality.
+/// Compare two Values for equality.
inline bool operator==(const DebugLocEntry::Value &A,
const DebugLocEntry::Value &B) {
if (A.EntryKind != B.EntryKind)
diff --git a/lib/CodeGen/AsmPrinter/DebugLocStream.h b/lib/CodeGen/AsmPrinter/DebugLocStream.h
index 0c551dfff9cc..8dcf5cbc1889 100644
--- a/lib/CodeGen/AsmPrinter/DebugLocStream.h
+++ b/lib/CodeGen/AsmPrinter/DebugLocStream.h
@@ -22,7 +22,7 @@ class DwarfCompileUnit;
class MachineInstr;
class MCSymbol;
-/// \brief Byte stream of .debug_loc entries.
+/// Byte stream of .debug_loc entries.
///
/// Stores a unified stream of .debug_loc entries. There's \a List for each
/// variable/inlined-at pair, and an \a Entry for each \a DebugLocEntry.
@@ -55,7 +55,7 @@ private:
SmallString<256> DWARFBytes;
SmallVector<std::string, 32> Comments;
- /// \brief Only verbose textual output needs comments. This will be set to
+ /// Only verbose textual output needs comments. This will be set to
/// true for that case, and false otherwise.
bool GenerateComments;
@@ -69,7 +69,7 @@ public:
class EntryBuilder;
private:
- /// \brief Start a new .debug_loc entry list.
+ /// Start a new .debug_loc entry list.
///
/// Start a new .debug_loc entry list. Return the new list's index so it can
/// be retrieved later via \a getList().
@@ -89,7 +89,7 @@ private:
/// \return false iff the list is deleted.
bool finalizeList(AsmPrinter &Asm);
- /// \brief Start a new .debug_loc entry.
+ /// Start a new .debug_loc entry.
///
/// Until the next call, bytes added to the stream will be added to this
/// entry.
diff --git a/lib/CodeGen/AsmPrinter/DwarfAccelTable.cpp b/lib/CodeGen/AsmPrinter/DwarfAccelTable.cpp
deleted file mode 100644
index c21b3d3451ad..000000000000
--- a/lib/CodeGen/AsmPrinter/DwarfAccelTable.cpp
+++ /dev/null
@@ -1,293 +0,0 @@
-//===- llvm/CodeGen/DwarfAccelTable.cpp - Dwarf Accelerator Tables --------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file contains support for writing dwarf accelerator tables.
-//
-//===----------------------------------------------------------------------===//
-
-#include "DwarfAccelTable.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/StringMap.h"
-#include "llvm/ADT/Twine.h"
-#include "llvm/BinaryFormat/Dwarf.h"
-#include "llvm/CodeGen/AsmPrinter.h"
-#include "llvm/CodeGen/DIE.h"
-#include "llvm/MC/MCExpr.h"
-#include "llvm/MC/MCStreamer.h"
-#include "llvm/Support/raw_ostream.h"
-#include <algorithm>
-#include <cassert>
-#include <cstddef>
-#include <cstdint>
-#include <iterator>
-#include <limits>
-#include <vector>
-
-using namespace llvm;
-
-// The length of the header data is always going to be 4 + 4 + 4*NumAtoms.
-DwarfAccelTable::DwarfAccelTable(ArrayRef<DwarfAccelTable::Atom> atomList)
- : Header(8 + (atomList.size() * 4)), HeaderData(atomList),
- Entries(Allocator) {}
-
-void DwarfAccelTable::AddName(DwarfStringPoolEntryRef Name, const DIE *die,
- char Flags) {
- assert(Data.empty() && "Already finalized!");
- // If the string is in the list already then add this die to the list
- // otherwise add a new one.
- DataArray &DIEs = Entries[Name.getString()];
- assert(!DIEs.Name || DIEs.Name == Name);
- DIEs.Name = Name;
- DIEs.Values.push_back(new (Allocator) HashDataContents(die, Flags));
-}
-
-void DwarfAccelTable::ComputeBucketCount() {
- // First get the number of unique hashes.
- std::vector<uint32_t> uniques(Data.size());
- for (size_t i = 0, e = Data.size(); i < e; ++i)
- uniques[i] = Data[i]->HashValue;
- array_pod_sort(uniques.begin(), uniques.end());
- std::vector<uint32_t>::iterator p =
- std::unique(uniques.begin(), uniques.end());
- uint32_t num = std::distance(uniques.begin(), p);
-
- // Then compute the bucket size, minimum of 1 bucket.
- if (num > 1024)
- Header.bucket_count = num / 4;
- else if (num > 16)
- Header.bucket_count = num / 2;
- else
- Header.bucket_count = num > 0 ? num : 1;
-
- Header.hashes_count = num;
-}
-
-// compareDIEs - comparison predicate that sorts DIEs by their offset.
-static bool compareDIEs(const DwarfAccelTable::HashDataContents *A,
- const DwarfAccelTable::HashDataContents *B) {
- return A->Die->getOffset() < B->Die->getOffset();
-}
-
-void DwarfAccelTable::FinalizeTable(AsmPrinter *Asm, StringRef Prefix) {
- // Create the individual hash data outputs.
- Data.reserve(Entries.size());
- for (StringMap<DataArray>::iterator EI = Entries.begin(), EE = Entries.end();
- EI != EE; ++EI) {
-
- // Unique the entries.
- std::stable_sort(EI->second.Values.begin(), EI->second.Values.end(), compareDIEs);
- EI->second.Values.erase(
- std::unique(EI->second.Values.begin(), EI->second.Values.end()),
- EI->second.Values.end());
-
- HashData *Entry = new (Allocator) HashData(EI->getKey(), EI->second);
- Data.push_back(Entry);
- }
-
- // Figure out how many buckets we need, then compute the bucket
- // contents and the final ordering. We'll emit the hashes and offsets
- // by doing a walk during the emission phase. We add temporary
- // symbols to the data so that we can reference them during the offset
- // later, we'll emit them when we emit the data.
- ComputeBucketCount();
-
- // Compute bucket contents and final ordering.
- Buckets.resize(Header.bucket_count);
- for (size_t i = 0, e = Data.size(); i < e; ++i) {
- uint32_t bucket = Data[i]->HashValue % Header.bucket_count;
- Buckets[bucket].push_back(Data[i]);
- Data[i]->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 (size_t i = 0; i < Buckets.size(); ++i)
- std::stable_sort(Buckets[i].begin(), Buckets[i].end(),
- [] (HashData *LHS, HashData *RHS) {
- return LHS->HashValue < RHS->HashValue;
- });
-}
-
-// Emits the header for the table via the AsmPrinter.
-void DwarfAccelTable::EmitHeader(AsmPrinter *Asm) {
- Asm->OutStreamer->AddComment("Header Magic");
- Asm->EmitInt32(Header.magic);
- Asm->OutStreamer->AddComment("Header Version");
- Asm->EmitInt16(Header.version);
- Asm->OutStreamer->AddComment("Header Hash Function");
- Asm->EmitInt16(Header.hash_function);
- Asm->OutStreamer->AddComment("Header Bucket Count");
- Asm->EmitInt32(Header.bucket_count);
- Asm->OutStreamer->AddComment("Header Hash Count");
- Asm->EmitInt32(Header.hashes_count);
- Asm->OutStreamer->AddComment("Header Data Length");
- Asm->EmitInt32(Header.header_data_len);
- Asm->OutStreamer->AddComment("HeaderData Die Offset Base");
- Asm->EmitInt32(HeaderData.die_offset_base);
- Asm->OutStreamer->AddComment("HeaderData Atom Count");
- Asm->EmitInt32(HeaderData.Atoms.size());
- for (size_t i = 0; i < HeaderData.Atoms.size(); i++) {
- Atom A = HeaderData.Atoms[i];
- Asm->OutStreamer->AddComment(dwarf::AtomTypeString(A.type));
- Asm->EmitInt16(A.type);
- Asm->OutStreamer->AddComment(dwarf::FormEncodingString(A.form));
- Asm->EmitInt16(A.form);
- }
-}
-
-// Walk through and emit the buckets for the table. Each index is
-// an offset into the list of hashes.
-void DwarfAccelTable::EmitBuckets(AsmPrinter *Asm) {
- unsigned index = 0;
- for (size_t i = 0, e = Buckets.size(); i < e; ++i) {
- Asm->OutStreamer->AddComment("Bucket " + Twine(i));
- if (!Buckets[i].empty())
- Asm->EmitInt32(index);
- else
- Asm->EmitInt32(std::numeric_limits<uint32_t>::max());
- // Buckets point in the list of hashes, not to the data. Do not
- // increment the index multiple times in case of hash collisions.
- uint64_t PrevHash = std::numeric_limits<uint64_t>::max();
- for (auto *HD : Buckets[i]) {
- uint32_t HashValue = HD->HashValue;
- if (PrevHash != HashValue)
- ++index;
- PrevHash = HashValue;
- }
- }
-}
-
-// Walk through the buckets and emit the individual hashes for each
-// bucket.
-void DwarfAccelTable::EmitHashes(AsmPrinter *Asm) {
- uint64_t PrevHash = std::numeric_limits<uint64_t>::max();
- for (size_t i = 0, e = Buckets.size(); i < e; ++i) {
- for (HashList::const_iterator HI = Buckets[i].begin(),
- HE = Buckets[i].end();
- HI != HE; ++HI) {
- uint32_t HashValue = (*HI)->HashValue;
- if (PrevHash == HashValue)
- continue;
- Asm->OutStreamer->AddComment("Hash in Bucket " + Twine(i));
- Asm->EmitInt32(HashValue);
- PrevHash = HashValue;
- }
- }
-}
-
-// Walk through the buckets and emit the individual offsets for each
-// element in each bucket. This is done via a symbol subtraction from the
-// beginning of the section. The non-section symbol will be output later
-// when we emit the actual data.
-void DwarfAccelTable::emitOffsets(AsmPrinter *Asm, const MCSymbol *SecBegin) {
- uint64_t PrevHash = std::numeric_limits<uint64_t>::max();
- for (size_t i = 0, e = Buckets.size(); i < e; ++i) {
- for (HashList::const_iterator HI = Buckets[i].begin(),
- HE = Buckets[i].end();
- HI != HE; ++HI) {
- uint32_t HashValue = (*HI)->HashValue;
- if (PrevHash == HashValue)
- continue;
- PrevHash = HashValue;
- Asm->OutStreamer->AddComment("Offset in Bucket " + Twine(i));
- MCContext &Context = Asm->OutStreamer->getContext();
- const MCExpr *Sub = MCBinaryExpr::createSub(
- MCSymbolRefExpr::create((*HI)->Sym, Context),
- MCSymbolRefExpr::create(SecBegin, Context), Context);
- Asm->OutStreamer->EmitValue(Sub, sizeof(uint32_t));
- }
- }
-}
-
-// Walk through the buckets and emit the full data for each element in
-// the bucket. For the string case emit the dies and the various offsets.
-// Terminate each HashData bucket with 0.
-void DwarfAccelTable::EmitData(AsmPrinter *Asm, DwarfDebug *D) {
- for (size_t i = 0, e = Buckets.size(); i < e; ++i) {
- uint64_t PrevHash = std::numeric_limits<uint64_t>::max();
- for (HashList::const_iterator HI = Buckets[i].begin(),
- HE = Buckets[i].end();
- HI != HE; ++HI) {
- // Terminate the previous entry if there is no hash collision
- // with the current one.
- if (PrevHash != std::numeric_limits<uint64_t>::max() &&
- PrevHash != (*HI)->HashValue)
- Asm->EmitInt32(0);
- // Remember to emit the label for our offset.
- Asm->OutStreamer->EmitLabel((*HI)->Sym);
- Asm->OutStreamer->AddComment((*HI)->Str);
- Asm->emitDwarfStringOffset((*HI)->Data.Name);
- Asm->OutStreamer->AddComment("Num DIEs");
- Asm->EmitInt32((*HI)->Data.Values.size());
- for (HashDataContents *HD : (*HI)->Data.Values) {
- // Emit the DIE offset
- Asm->EmitInt32(HD->Die->getDebugSectionOffset());
- // If we have multiple Atoms emit that info too.
- // FIXME: A bit of a hack, we either emit only one atom or all info.
- if (HeaderData.Atoms.size() > 1) {
- Asm->EmitInt16(HD->Die->getTag());
- Asm->EmitInt8(HD->Flags);
- }
- }
- PrevHash = (*HI)->HashValue;
- }
- // Emit the final end marker for the bucket.
- if (!Buckets[i].empty())
- Asm->EmitInt32(0);
- }
-}
-
-// Emit the entire data structure to the output file.
-void DwarfAccelTable::emit(AsmPrinter *Asm, const MCSymbol *SecBegin,
- DwarfDebug *D) {
- // Emit the header.
- EmitHeader(Asm);
-
- // Emit the buckets.
- EmitBuckets(Asm);
-
- // Emit the hashes.
- EmitHashes(Asm);
-
- // Emit the offsets.
- emitOffsets(Asm, SecBegin);
-
- // Emit the hash data.
- EmitData(Asm, D);
-}
-
-#ifndef NDEBUG
-void DwarfAccelTable::print(raw_ostream &OS) {
- Header.print(OS);
- HeaderData.print(OS);
-
- OS << "Entries: \n";
- for (StringMap<DataArray>::const_iterator EI = Entries.begin(),
- EE = Entries.end();
- EI != EE; ++EI) {
- OS << "Name: " << EI->getKeyData() << "\n";
- for (HashDataContents *HD : EI->second.Values)
- HD->print(OS);
- }
-
- OS << "Buckets and Hashes: \n";
- for (size_t i = 0, e = Buckets.size(); i < e; ++i)
- for (HashList::const_iterator HI = Buckets[i].begin(),
- HE = Buckets[i].end();
- HI != HE; ++HI)
- (*HI)->print(OS);
-
- OS << "Data: \n";
- for (std::vector<HashData *>::const_iterator DI = Data.begin(),
- DE = Data.end();
- DI != DE; ++DI)
- (*DI)->print(OS);
-}
-#endif
diff --git a/lib/CodeGen/AsmPrinter/DwarfAccelTable.h b/lib/CodeGen/AsmPrinter/DwarfAccelTable.h
deleted file mode 100644
index f56199dc8e72..000000000000
--- a/lib/CodeGen/AsmPrinter/DwarfAccelTable.h
+++ /dev/null
@@ -1,261 +0,0 @@
-//==- llvm/CodeGen/DwarfAccelTable.h - Dwarf Accelerator Tables --*- C++ -*-==//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file contains support for writing dwarf accelerator tables.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_LIB_CODEGEN_ASMPRINTER_DWARFACCELTABLE_H
-#define LLVM_LIB_CODEGEN_ASMPRINTER_DWARFACCELTABLE_H
-
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/StringMap.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/BinaryFormat/Dwarf.h"
-#include "llvm/CodeGen/DIE.h"
-#include "llvm/CodeGen/DwarfStringPoolEntry.h"
-#include "llvm/MC/MCSymbol.h"
-#include "llvm/Support/Allocator.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/Format.h"
-#include "llvm/Support/raw_ostream.h"
-#include <cstddef>
-#include <cstdint>
-#include <vector>
-
-// The dwarf accelerator tables are an indirect hash table optimized
-// for null lookup rather than access to known data. They are output into
-// an on-disk format that looks like this:
-//
-// .-------------.
-// | HEADER |
-// |-------------|
-// | BUCKETS |
-// |-------------|
-// | HASHES |
-// |-------------|
-// | OFFSETS |
-// |-------------|
-// | DATA |
-// `-------------'
-//
-// where the header contains a magic number, version, type of hash function,
-// the number of buckets, total number of hashes, and room for a special
-// struct of data and the length of that struct.
-//
-// The buckets contain an index (e.g. 6) into the hashes array. The hashes
-// section contains all of the 32-bit hash values in contiguous memory, and
-// the offsets contain the offset into the data area for the particular
-// hash.
-//
-// For a lookup example, we could hash a function name and take it modulo the
-// number of buckets giving us our bucket. From there we take the bucket value
-// as an index into the hashes table and look at each successive hash as long
-// as the hash value is still the same modulo result (bucket value) as earlier.
-// If we have a match we look at that same entry in the offsets table and
-// grab the offset in the data for our final match.
-
-namespace llvm {
-
-class AsmPrinter;
-class DwarfDebug;
-
-class DwarfAccelTable {
- // Helper function to compute the number of buckets needed based on
- // the number of unique hashes.
- void ComputeBucketCount();
-
- struct TableHeader {
- uint32_t magic = MagicHash; // 'HASH' magic value to allow endian detection
- uint16_t version = 1; // Version number.
- uint16_t hash_function = dwarf::DW_hash_function_djb;
- // The hash function enumeration that was used.
- uint32_t bucket_count = 0; // The number of buckets in this hash table.
- uint32_t hashes_count = 0; // The total number of unique hash values
- // and hash data offsets in this table.
- uint32_t header_data_len; // The bytes to skip to get to the hash
- // indexes (buckets) for correct alignment.
- // Also written to disk is the implementation specific header data.
-
- static const uint32_t MagicHash = 0x48415348;
-
- TableHeader(uint32_t data_len) : header_data_len(data_len) {}
-
-#ifndef NDEBUG
- void print(raw_ostream &OS) {
- OS << "Magic: " << format("0x%x", magic) << "\n"
- << "Version: " << version << "\n"
- << "Hash Function: " << hash_function << "\n"
- << "Bucket Count: " << bucket_count << "\n"
- << "Header Data Length: " << header_data_len << "\n";
- }
-
- void dump() { print(dbgs()); }
-#endif
- };
-
-public:
- // The HeaderData describes the form of each set of data. In general this
- // is as a list of atoms (atom_count) where each atom contains a type
- // (AtomType type) of data, and an encoding form (form). In the case of
- // data that is referenced via DW_FORM_ref_* the die_offset_base is
- // used to describe the offset for all forms in the list of atoms.
- // This also serves as a public interface of sorts.
- // When written to disk this will have the form:
- //
- // uint32_t die_offset_base
- // uint32_t atom_count
- // atom_count Atoms
-
- // Make these public so that they can be used as a general interface to
- // the class.
- struct Atom {
- uint16_t type; // enum AtomType
- uint16_t form; // DWARF DW_FORM_ defines
-
- constexpr Atom(uint16_t type, uint16_t form) : type(type), form(form) {}
-
-#ifndef NDEBUG
- void print(raw_ostream &OS) {
- OS << "Type: " << dwarf::AtomTypeString(type) << "\n"
- << "Form: " << dwarf::FormEncodingString(form) << "\n";
- }
-
- void dump() { print(dbgs()); }
-#endif
- };
-
-private:
- struct TableHeaderData {
- uint32_t die_offset_base;
- SmallVector<Atom, 3> Atoms;
-
- TableHeaderData(ArrayRef<Atom> AtomList, uint32_t offset = 0)
- : die_offset_base(offset), Atoms(AtomList.begin(), AtomList.end()) {}
-
-#ifndef NDEBUG
- void print(raw_ostream &OS) {
- OS << "die_offset_base: " << die_offset_base << "\n";
- for (size_t i = 0; i < Atoms.size(); i++)
- Atoms[i].print(OS);
- }
-
- void dump() { print(dbgs()); }
-#endif
- };
-
- // The data itself consists of a str_offset, a count of the DIEs in the
- // hash and the offsets to the DIEs themselves.
- // On disk each data section is ended with a 0 KeyType as the end of the
- // hash chain.
- // On output this looks like:
- // uint32_t str_offset
- // uint32_t hash_data_count
- // HashData[hash_data_count]
-public:
- struct HashDataContents {
- const DIE *Die; // Offsets
- char Flags; // Specific flags to output
-
- HashDataContents(const DIE *D, char Flags) : Die(D), Flags(Flags) {}
-
-#ifndef NDEBUG
- void print(raw_ostream &OS) const {
- OS << " Offset: " << Die->getOffset() << "\n"
- << " Tag: " << dwarf::TagString(Die->getTag()) << "\n"
- << " Flags: " << Flags << "\n";
- }
-#endif
- };
-
-private:
- // String Data
- struct DataArray {
- DwarfStringPoolEntryRef Name;
- std::vector<HashDataContents *> Values;
- };
-
- friend struct HashData;
-
- struct HashData {
- StringRef Str;
- uint32_t HashValue;
- MCSymbol *Sym;
- DwarfAccelTable::DataArray &Data; // offsets
-
- HashData(StringRef S, DwarfAccelTable::DataArray &Data)
- : Str(S), Data(Data) {
- HashValue = dwarf::djbHash(S);
- }
-
-#ifndef NDEBUG
- void print(raw_ostream &OS) {
- OS << "Name: " << Str << "\n";
- OS << " Hash Value: " << format("0x%x", HashValue) << "\n";
- OS << " Symbol: ";
- if (Sym)
- OS << *Sym;
- else
- OS << "<none>";
- OS << "\n";
- for (HashDataContents *C : Data.Values) {
- OS << " Offset: " << C->Die->getOffset() << "\n";
- OS << " Tag: " << dwarf::TagString(C->Die->getTag()) << "\n";
- OS << " Flags: " << C->Flags << "\n";
- }
- }
-
- void dump() { print(dbgs()); }
-#endif
- };
-
- // Internal Functions
- void EmitHeader(AsmPrinter *);
- void EmitBuckets(AsmPrinter *);
- void EmitHashes(AsmPrinter *);
- void emitOffsets(AsmPrinter *, const MCSymbol *);
- void EmitData(AsmPrinter *, DwarfDebug *D);
-
- // Allocator for HashData and HashDataContents.
- BumpPtrAllocator Allocator;
-
- // Output Variables
- TableHeader Header;
- TableHeaderData HeaderData;
- std::vector<HashData *> Data;
-
- using StringEntries = StringMap<DataArray, BumpPtrAllocator &>;
-
- StringEntries Entries;
-
- // Buckets/Hashes/Offsets
- using HashList = std::vector<HashData *>;
- using BucketList = std::vector<HashList>;
- BucketList Buckets;
- HashList Hashes;
-
- // Public Implementation
-public:
- DwarfAccelTable(ArrayRef<DwarfAccelTable::Atom>);
- DwarfAccelTable(const DwarfAccelTable &) = delete;
- DwarfAccelTable &operator=(const DwarfAccelTable &) = delete;
-
- void AddName(DwarfStringPoolEntryRef Name, const DIE *Die, char Flags = 0);
- void FinalizeTable(AsmPrinter *, StringRef);
- void emit(AsmPrinter *, const MCSymbol *, DwarfDebug *);
-#ifndef NDEBUG
- void print(raw_ostream &OS);
- void dump() { print(dbgs()); }
-#endif
-};
-
-} // end namespace llvm
-
-#endif // LLVM_LIB_CODEGEN_ASMPRINTER_DWARFACCELTABLE_H
diff --git a/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp b/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp
index cbb4c48b4d88..1990456cc555 100644
--- a/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp
+++ b/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp
@@ -17,7 +17,6 @@
#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
-#include "llvm/CodeGen/TargetLoweringObjectFile.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/Mangler.h"
#include "llvm/IR/Module.h"
@@ -30,6 +29,7 @@
#include "llvm/MC/MachineLocation.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FormattedStream.h"
+#include "llvm/Target/TargetLoweringObjectFile.h"
#include "llvm/Target/TargetOptions.h"
using namespace llvm;
diff --git a/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp b/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
index c8cd8eb8ffd3..32271a0ef24a 100644
--- a/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
+++ b/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
@@ -28,7 +28,6 @@
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineOperand.h"
#include "llvm/CodeGen/TargetFrameLowering.h"
-#include "llvm/CodeGen/TargetLoweringObjectFile.h"
#include "llvm/CodeGen/TargetRegisterInfo.h"
#include "llvm/CodeGen/TargetSubtargetInfo.h"
#include "llvm/IR/DataLayout.h"
@@ -40,6 +39,7 @@
#include "llvm/MC/MCSymbol.h"
#include "llvm/MC/MachineLocation.h"
#include "llvm/Support/Casting.h"
+#include "llvm/Target/TargetLoweringObjectFile.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetOptions.h"
#include <algorithm>
@@ -94,16 +94,18 @@ void DwarfCompileUnit::addLocalLabelAddress(DIE &Die,
DIEInteger(0));
}
-unsigned DwarfCompileUnit::getOrCreateSourceID(StringRef FileName,
- StringRef DirName) {
+unsigned DwarfCompileUnit::getOrCreateSourceID(const DIFile *File) {
// If we print assembly, we can't separate .file entries according to
// compile units. Thus all files will belong to the default compile unit.
// FIXME: add a better feature test than hasRawTextSupport. Even better,
// extend .file to support this.
+ unsigned CUID = Asm->OutStreamer->hasRawTextSupport() ? 0 : getUniqueID();
+ if (!File)
+ return Asm->OutStreamer->EmitDwarfFileDirective(0, "", "", nullptr, None, CUID);
return Asm->OutStreamer->EmitDwarfFileDirective(
- 0, DirName, FileName,
- Asm->OutStreamer->hasRawTextSupport() ? 0 : getUniqueID());
+ 0, File->getDirectory(), File->getFilename(), getMD5AsBytes(File),
+ File->getSource(), CUID);
}
DIE *DwarfCompileUnit::getOrCreateGlobalVariableDIE(
@@ -190,10 +192,13 @@ DIE *DwarfCompileUnit::getOrCreateGlobalVariableDIE(
DwarfExpr = llvm::make_unique<DIEDwarfExpression>(*Asm, *this, *Loc);
}
+ if (Expr)
+ DwarfExpr->addFragmentOffset(Expr);
+
if (Global) {
const MCSymbol *Sym = Asm->getSymbol(Global);
if (Global->isThreadLocal()) {
- if (Asm->TM.Options.EmulatedTLS) {
+ if (Asm->TM.useEmulatedTLS()) {
// TODO: add debug info for emulated thread local mode.
} else {
// FIXME: Make this work with -gsplit-dwarf.
@@ -225,10 +230,13 @@ DIE *DwarfCompileUnit::getOrCreateGlobalVariableDIE(
addOpAddress(*Loc, Sym);
}
}
- if (Expr) {
- DwarfExpr->addFragmentOffset(Expr);
- DwarfExpr->addExpression(Expr);
- }
+ // Global variables attached to symbols are memory locations.
+ // It would be better if this were unconditional, but malformed input that
+ // mixes non-fragments and fragments for the same variable is too expensive
+ // to detect in the verifier.
+ if (DwarfExpr->isUnknownLocation())
+ DwarfExpr->setMemoryLocationKind();
+ DwarfExpr->addExpression(Expr);
}
if (Loc)
addBlock(*VariableDIE, dwarf::DW_AT_location, DwarfExpr->finalize());
@@ -241,7 +249,8 @@ DIE *DwarfCompileUnit::getOrCreateGlobalVariableDIE(
// If the linkage name is different than the name, go ahead and output
// that as well into the name table.
- if (GV->getLinkageName() != "" && GV->getName() != GV->getLinkageName())
+ if (GV->getLinkageName() != "" && GV->getName() != GV->getLinkageName() &&
+ DD->useAllLinkageNames())
DD->addAccelName(GV->getLinkageName(), *VariableDIE);
}
@@ -267,15 +276,20 @@ void DwarfCompileUnit::addRange(RangeSpan Range) {
void DwarfCompileUnit::initStmtList() {
// Define start line table label for each Compile Unit.
- MCSymbol *LineTableStartSym =
- Asm->OutStreamer->getDwarfLineTableSymbol(getUniqueID());
+ MCSymbol *LineTableStartSym;
+ const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering();
+ if (DD->useSectionsAsReferences()) {
+ LineTableStartSym = TLOF.getDwarfLineSection()->getBeginSymbol();
+ } else {
+ LineTableStartSym =
+ Asm->OutStreamer->getDwarfLineTableSymbol(getUniqueID());
+ }
// DW_AT_stmt_list is a offset of line number information for this
// compile unit in debug_line section. For split dwarf this is
// left in the skeleton CU and so not included.
// The line table entries are not always emitted in assembly, so it
// is not okay to use line_table_start here.
- const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering();
StmtListValue =
addSectionLabel(getUnitDie(), dwarf::DW_AT_stmt_list, LineTableStartSym,
TLOF.getDwarfLineSection()->getBeginSymbol());
@@ -313,10 +327,16 @@ DIE &DwarfCompileUnit::updateSubprogramScopeDIE(const DISubprogram *SP) {
// Only include DW_AT_frame_base in full debug info
if (!includeMinimalInlineScopes()) {
- const TargetRegisterInfo *RI = Asm->MF->getSubtarget().getRegisterInfo();
- MachineLocation Location(RI->getFrameRegister(*Asm->MF));
- if (RI->isPhysicalRegister(Location.getReg()))
- addAddress(*SPDie, dwarf::DW_AT_frame_base, Location);
+ if (Asm->MF->getTarget().getTargetTriple().isNVPTX()) {
+ DIELoc *Loc = new (DIEValueAllocator) DIELoc;
+ addUInt(*Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_call_frame_cfa);
+ addBlock(*SPDie, dwarf::DW_AT_frame_base, Loc);
+ } else {
+ const TargetRegisterInfo *RI = Asm->MF->getSubtarget().getRegisterInfo();
+ MachineLocation Location(RI->getFrameRegister(*Asm->MF));
+ if (RI->isPhysicalRegister(Location.getReg()))
+ addAddress(*SPDie, dwarf::DW_AT_frame_base, Location);
+ }
}
// Add name to the name table, we do this here because we're guaranteed
@@ -385,21 +405,28 @@ void DwarfCompileUnit::addScopeRangeList(DIE &ScopeDIE,
SmallVector<RangeSpan, 2> Range) {
const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering();
- // Emit offset in .debug_range as a relocatable label. emitDIE will handle
- // emitting it appropriately.
+ // Emit the offset into .debug_ranges or .debug_rnglists as a relocatable
+ // label. emitDIE() will handle emitting it appropriately.
const MCSymbol *RangeSectionSym =
- TLOF.getDwarfRangesSection()->getBeginSymbol();
+ DD->getDwarfVersion() >= 5
+ ? TLOF.getDwarfRnglistsSection()->getBeginSymbol()
+ : TLOF.getDwarfRangesSection()->getBeginSymbol();
RangeSpanList List(Asm->createTempSymbol("debug_ranges"), std::move(Range));
// Under fission, ranges are specified by constant offsets relative to the
// CU's DW_AT_GNU_ranges_base.
- if (isDwoUnit())
- addSectionDelta(ScopeDIE, dwarf::DW_AT_ranges, List.getSym(),
- RangeSectionSym);
- else
+ // FIXME: For DWARF v5, do not generate the DW_AT_ranges attribute under
+ // fission until we support the forms using the .debug_addr section
+ // (DW_RLE_startx_endx etc.).
+ if (isDwoUnit()) {
+ if (DD->getDwarfVersion() < 5)
+ addSectionDelta(ScopeDIE, dwarf::DW_AT_ranges, List.getSym(),
+ RangeSectionSym);
+ } else {
addSectionLabel(ScopeDIE, dwarf::DW_AT_ranges, List.getSym(),
RangeSectionSym);
+ }
// Add the range list to the set of ranges to be emitted.
(Skeleton ? Skeleton : this)->CURangeLists.push_back(std::move(List));
@@ -407,9 +434,10 @@ void DwarfCompileUnit::addScopeRangeList(DIE &ScopeDIE,
void DwarfCompileUnit::attachRangesOrLowHighPC(
DIE &Die, SmallVector<RangeSpan, 2> Ranges) {
- if (Ranges.size() == 1) {
- const auto &single = Ranges.front();
- attachLowHighPC(Die, single.getStart(), single.getEnd());
+ if (Ranges.size() == 1 || !DD->useRangesSection()) {
+ const RangeSpan &Front = Ranges.front();
+ const RangeSpan &Back = Ranges.back();
+ attachLowHighPC(Die, Front.getStart(), Back.getEnd());
} else
addScopeRangeList(Die, std::move(Ranges));
}
@@ -443,7 +471,7 @@ DIE *DwarfCompileUnit::constructInlinedScopeDIE(LexicalScope *Scope) {
// Add the call site information to the DIE.
const DILocation *IA = Scope->getInlinedAt();
addUInt(*ScopeDIE, dwarf::DW_AT_call_file, None,
- getOrCreateSourceID(IA->getFilename(), IA->getDirectory()));
+ getOrCreateSourceID(IA->getFile()));
addUInt(*ScopeDIE, dwarf::DW_AT_call_line, None, IA->getLine());
if (IA->getDiscriminator() && DD->getDwarfVersion() >= 4)
addUInt(*ScopeDIE, dwarf::DW_AT_GNU_discriminator, None,
@@ -482,6 +510,7 @@ DIE *DwarfCompileUnit::constructVariableDIEImpl(const DbgVariable &DV,
bool Abstract) {
// Define variable debug information entry.
auto VariableDie = DIE::get(DIEValueAllocator, DV.getTag());
+ insertDIE(DV.getVariable(), VariableDie);
if (Abstract) {
applyVariableAttributes(DV, *VariableDie);
@@ -547,8 +576,11 @@ DIE *DwarfCompileUnit::constructVariableDIEImpl(const DbgVariable &DV,
Ops.append(Expr->elements_begin(), Expr->elements_end());
DIExpressionCursor Cursor(Ops);
DwarfExpr.setMemoryLocationKind();
- DwarfExpr.addMachineRegExpression(
- *Asm->MF->getSubtarget().getRegisterInfo(), Cursor, FrameReg);
+ if (const MCSymbol *FrameSymbol = Asm->getFunctionFrameSymbol())
+ addOpAddress(*Loc, FrameSymbol);
+ else
+ DwarfExpr.addMachineRegExpression(
+ *Asm->MF->getSubtarget().getRegisterInfo(), Cursor, FrameReg);
DwarfExpr.addExpression(std::move(Cursor));
}
addBlock(*VariableDie, dwarf::DW_AT_location, DwarfExpr.finalize());
@@ -565,13 +597,95 @@ DIE *DwarfCompileUnit::constructVariableDIE(DbgVariable &DV,
return Var;
}
+/// Return all DIVariables that appear in count: expressions.
+static SmallVector<const DIVariable *, 2> dependencies(DbgVariable *Var) {
+ SmallVector<const DIVariable *, 2> Result;
+ auto *Array = dyn_cast<DICompositeType>(Var->getType());
+ if (!Array || Array->getTag() != dwarf::DW_TAG_array_type)
+ return Result;
+ for (auto *El : Array->getElements()) {
+ if (auto *Subrange = dyn_cast<DISubrange>(El)) {
+ auto Count = Subrange->getCount();
+ if (auto *Dependency = Count.dyn_cast<DIVariable *>())
+ Result.push_back(Dependency);
+ }
+ }
+ return Result;
+}
+
+/// Sort local variables so that variables appearing inside of helper
+/// expressions come first.
+static SmallVector<DbgVariable *, 8>
+sortLocalVars(SmallVectorImpl<DbgVariable *> &Input) {
+ SmallVector<DbgVariable *, 8> Result;
+ SmallVector<PointerIntPair<DbgVariable *, 1>, 8> WorkList;
+ // Map back from a DIVariable to its containing DbgVariable.
+ SmallDenseMap<const DILocalVariable *, DbgVariable *> DbgVar;
+ // Set of DbgVariables in Result.
+ SmallDenseSet<DbgVariable *, 8> Visited;
+ // For cycle detection.
+ SmallDenseSet<DbgVariable *, 8> Visiting;
+
+ // Initialize the worklist and the DIVariable lookup table.
+ for (auto Var : reverse(Input)) {
+ DbgVar.insert({Var->getVariable(), Var});
+ WorkList.push_back({Var, 0});
+ }
+
+ // Perform a stable topological sort by doing a DFS.
+ while (!WorkList.empty()) {
+ auto Item = WorkList.back();
+ DbgVariable *Var = Item.getPointer();
+ bool visitedAllDependencies = Item.getInt();
+ WorkList.pop_back();
+
+ // Dependency is in a different lexical scope or a global.
+ if (!Var)
+ continue;
+
+ // Already handled.
+ if (Visited.count(Var))
+ continue;
+
+ // Add to Result if all dependencies are visited.
+ if (visitedAllDependencies) {
+ Visited.insert(Var);
+ Result.push_back(Var);
+ continue;
+ }
+
+ // Detect cycles.
+ auto Res = Visiting.insert(Var);
+ if (!Res.second) {
+ assert(false && "dependency cycle in local variables");
+ return Result;
+ }
+
+ // Push dependencies and this node onto the worklist, so that this node is
+ // visited again after all of its dependencies are handled.
+ WorkList.push_back({Var, 1});
+ for (auto *Dependency : dependencies(Var)) {
+ auto Dep = dyn_cast_or_null<const DILocalVariable>(Dependency);
+ WorkList.push_back({DbgVar[Dep], 0});
+ }
+ }
+ return Result;
+}
+
DIE *DwarfCompileUnit::createScopeChildrenDIE(LexicalScope *Scope,
SmallVectorImpl<DIE *> &Children,
bool *HasNonScopeChildren) {
assert(Children.empty());
DIE *ObjectPointer = nullptr;
- for (DbgVariable *DV : DU->getScopeVariables().lookup(Scope))
+ // Emit function arguments (order is significant).
+ auto Vars = DU->getScopeVariables().lookup(Scope);
+ for (auto &DV : Vars.Args)
+ Children.push_back(constructVariableDIE(*DV.second, *Scope, ObjectPointer));
+
+ // Emit local variables.
+ auto Locals = sortLocalVars(Vars.Locals);
+ for (DbgVariable *DV : Locals)
Children.push_back(constructVariableDIE(*DV, *Scope, ObjectPointer));
// Skip imported directives in gmlt-like data.
@@ -687,9 +801,7 @@ DIE *DwarfCompileUnit::constructImportedEntityDIE(
else
EntityDie = getDIE(Entity);
assert(EntityDie);
- auto *File = Module->getFile();
- addSourceLine(*IMDie, Module->getLine(), File ? File->getFilename() : "",
- File ? File->getDirectory() : "");
+ addSourceLine(*IMDie, Module->getLine(), Module->getFile());
addDIEEntry(*IMDie, dwarf::DW_AT_import, *EntityDie);
StringRef Name = Module->getName();
if (!Name.empty())
@@ -750,7 +862,7 @@ void DwarfCompileUnit::createAbstractVariable(const DILocalVariable *Var,
void DwarfCompileUnit::emitHeader(bool UseOffsets) {
// Don't bother labeling the .dwo unit, as its offset isn't used.
- if (!Skeleton) {
+ if (!Skeleton && !DD->useSectionsAsReferences()) {
LabelBegin = Asm->createTempSymbol("cu_begin");
Asm->OutStreamer->EmitLabel(LabelBegin);
}
@@ -759,6 +871,8 @@ void DwarfCompileUnit::emitHeader(bool UseOffsets) {
: DD->useSplitDwarf() ? dwarf::DW_UT_skeleton
: dwarf::DW_UT_compile;
DwarfUnit::emitCommonHeader(UseOffsets, UT);
+ if (DD->getDwarfVersion() >= 5 && UT != dwarf::DW_UT_compile)
+ Asm->emitInt64(getDWOId());
}
bool DwarfCompileUnit::hasDwarfPubSections() const {
@@ -767,7 +881,8 @@ bool DwarfCompileUnit::hasDwarfPubSections() const {
if (CUNode->getGnuPubnames())
return true;
- return DD->tuneForGDB() && !includeMinimalInlineScopes();
+ return DD->tuneForGDB() && DD->usePubSections() &&
+ !includeMinimalInlineScopes();
}
/// addGlobalName - Add a new global name to the compile unit.
diff --git a/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h b/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h
index 68482eb7e358..51e1558fe4a3 100644
--- a/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h
+++ b/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h
@@ -83,7 +83,10 @@ class DwarfCompileUnit final : public DwarfUnit {
DenseMap<const MDNode *, DIE *> AbstractSPDies;
DenseMap<const MDNode *, std::unique_ptr<DbgVariable>> AbstractVariables;
- /// \brief Construct a DIE for the given DbgVariable without initializing the
+ /// DWO ID for correlating skeleton and split units.
+ uint64_t DWOId = 0;
+
+ /// Construct a DIE for the given DbgVariable without initializing the
/// DbgVariable's DIE reference.
DIE *constructVariableDIEImpl(const DbgVariable &DV, bool Abstract);
@@ -141,7 +144,7 @@ public:
DwarfCompileUnit &getCU() override { return *this; }
- unsigned getOrCreateSourceID(StringRef FileName, StringRef DirName) override;
+ unsigned getOrCreateSourceID(const DIFile *File) override;
void addImportedEntity(const DIImportedEntity* IE) {
DIScope *Scope = IE->getScope();
@@ -159,7 +162,7 @@ public:
void attachLowHighPC(DIE &D, const MCSymbol *Begin, const MCSymbol *End);
- /// \brief Find DIE for the given subprogram and attach appropriate
+ /// Find DIE for the given subprogram and attach appropriate
/// DW_AT_low_pc and DW_AT_high_pc attributes. If there are global
/// variables in this scope then create and insert DIEs for these
/// variables.
@@ -168,7 +171,7 @@ public:
void constructScopeDIE(LexicalScope *Scope,
SmallVectorImpl<DIE *> &FinalChildren);
- /// \brief A helper function to construct a RangeSpanList for a given
+ /// A helper function to construct a RangeSpanList for a given
/// lexical scope.
void addScopeRangeList(DIE &ScopeDIE, SmallVector<RangeSpan, 2> Range);
@@ -177,11 +180,11 @@ public:
void attachRangesOrLowHighPC(DIE &D,
const SmallVectorImpl<InsnRange> &Ranges);
- /// \brief This scope represents inlined body of a function. Construct
+ /// This scope represents inlined body of a function. Construct
/// DIE to represent this concrete inlined copy of the function.
DIE *constructInlinedScopeDIE(LexicalScope *Scope);
- /// \brief Construct new DW_TAG_lexical_block for this scope and
+ /// Construct new DW_TAG_lexical_block for this scope and
/// attach DW_AT_low_pc/DW_AT_high_pc labels.
DIE *constructLexicalScopeDIE(LexicalScope *Scope);
@@ -196,14 +199,14 @@ public:
SmallVectorImpl<DIE *> &Children,
bool *HasNonScopeChildren = nullptr);
- /// \brief Construct a DIE for this subprogram scope.
+ /// Construct a DIE for this subprogram scope.
void constructSubprogramScopeDIE(const DISubprogram *Sub, LexicalScope *Scope);
DIE *createAndAddScopeChildren(LexicalScope *Scope, DIE &ScopeDIE);
void constructAbstractSubprogramScopeDIE(LexicalScope *Scope);
- /// \brief Construct import_module DIE.
+ /// Construct import_module DIE.
DIE *constructImportedEntityDIE(const DIImportedEntity *Module);
void finishSubprogramDefinition(const DISubprogram *SP);
@@ -214,11 +217,18 @@ public:
DbgVariable *getExistingAbstractVariable(InlinedVariable IV,
const DILocalVariable *&Cleansed);
DbgVariable *getExistingAbstractVariable(InlinedVariable IV);
- void createAbstractVariable(const DILocalVariable *DV, LexicalScope *Scope);
+ void createAbstractVariable(const DILocalVariable *Var, LexicalScope *Scope);
/// Set the skeleton unit associated with this unit.
void setSkeleton(DwarfCompileUnit &Skel) { Skeleton = &Skel; }
+ unsigned getHeaderSize() const override {
+ // DWARF v5 added the DWO ID to the header for split/skeleton units.
+ unsigned DWOIdSize =
+ DD->getDwarfVersion() >= 5 && DD->useSplitDwarf() ? sizeof(uint64_t)
+ : 0;
+ return DwarfUnit::getHeaderSize() + DWOIdSize;
+ }
unsigned getLength() {
return sizeof(uint32_t) + // Length field
getHeaderSize() + getUnitDie().getSize();
@@ -290,6 +300,9 @@ public:
void setBaseAddress(const MCSymbol *Base) { BaseAddress = Base; }
const MCSymbol *getBaseAddress() const { return BaseAddress; }
+ uint64_t getDWOId() const { return DWOId; }
+ void setDWOId(uint64_t DwoId) { DWOId = DwoId; }
+
bool hasDwarfPubSections() const;
};
diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
index 2c9c7d4f3146..8761fae9dd22 100644
--- a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
+++ b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
@@ -16,7 +16,6 @@
#include "DIEHash.h"
#include "DebugLocEntry.h"
#include "DebugLocStream.h"
-#include "DwarfAccelTable.h"
#include "DwarfCompileUnit.h"
#include "DwarfExpression.h"
#include "DwarfFile.h"
@@ -31,6 +30,7 @@
#include "llvm/ADT/Triple.h"
#include "llvm/ADT/Twine.h"
#include "llvm/BinaryFormat/Dwarf.h"
+#include "llvm/CodeGen/AccelTable.h"
#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/CodeGen/DIE.h"
#include "llvm/CodeGen/LexicalScopes.h"
@@ -39,7 +39,6 @@
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/CodeGen/MachineOperand.h"
-#include "llvm/CodeGen/TargetLoweringObjectFile.h"
#include "llvm/CodeGen/TargetRegisterInfo.h"
#include "llvm/CodeGen/TargetSubtargetInfo.h"
#include "llvm/IR/Constants.h"
@@ -66,6 +65,7 @@
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/Timer.h"
#include "llvm/Support/raw_ostream.h"
+#include "llvm/Target/TargetLoweringObjectFile.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetOptions.h"
#include <algorithm>
@@ -94,6 +94,11 @@ static cl::opt<bool> GenerateARangeSection("generate-arange-section",
cl::desc("Generate dwarf aranges"),
cl::init(false));
+static cl::opt<bool>
+ GenerateDwarfTypeUnits("generate-type-units", cl::Hidden,
+ cl::desc("Generate DWARF4 type units."),
+ cl::init(false));
+
static cl::opt<bool> SplitDwarfCrossCuReferences(
"split-dwarf-cross-cu-references", cl::Hidden,
cl::desc("Enable cross-cu references in DWO files"), cl::init(false));
@@ -107,14 +112,40 @@ static cl::opt<DefaultOnOff> UnknownLocations(
clEnumVal(Enable, "In all cases"), clEnumVal(Disable, "Never")),
cl::init(Default));
+static cl::opt<AccelTableKind> AccelTables(
+ "accel-tables", cl::Hidden, cl::desc("Output dwarf accelerator tables."),
+ cl::values(clEnumValN(AccelTableKind::Default, "Default",
+ "Default for platform"),
+ clEnumValN(AccelTableKind::None, "Disable", "Disabled."),
+ clEnumValN(AccelTableKind::Apple, "Apple", "Apple"),
+ clEnumValN(AccelTableKind::Dwarf, "Dwarf", "DWARF")),
+ cl::init(AccelTableKind::Default));
+
static cl::opt<DefaultOnOff>
-DwarfAccelTables("dwarf-accel-tables", cl::Hidden,
- cl::desc("Output prototype dwarf accelerator tables."),
+DwarfInlinedStrings("dwarf-inlined-strings", cl::Hidden,
+ cl::desc("Use inlined strings rather than string section."),
cl::values(clEnumVal(Default, "Default for platform"),
clEnumVal(Enable, "Enabled"),
clEnumVal(Disable, "Disabled")),
cl::init(Default));
+static cl::opt<bool>
+ NoDwarfPubSections("no-dwarf-pub-sections", cl::Hidden,
+ cl::desc("Disable emission of DWARF pub sections."),
+ cl::init(false));
+
+static cl::opt<bool>
+ NoDwarfRangesSection("no-dwarf-ranges-section", cl::Hidden,
+ cl::desc("Disable emission .debug_ranges section."),
+ cl::init(false));
+
+static cl::opt<DefaultOnOff> DwarfSectionsAsReferences(
+ "dwarf-sections-as-references", cl::Hidden,
+ cl::desc("Use sections+offset as references rather than labels."),
+ cl::values(clEnumVal(Default, "Default for platform"),
+ clEnumVal(Enable, "Enabled"), clEnumVal(Disable, "Disabled")),
+ cl::init(Default));
+
enum LinkageNameOption {
DefaultLinkageNames,
AllLinkageNames,
@@ -215,11 +246,11 @@ ArrayRef<DbgVariable::FrameIndexExpr> DbgVariable::getFrameIndexExprs() const {
return A.Expr->isFragment();
}) &&
"multiple FI expressions without DW_OP_LLVM_fragment");
- std::sort(FrameIndexExprs.begin(), FrameIndexExprs.end(),
- [](const FrameIndexExpr &A, const FrameIndexExpr &B) -> bool {
- return A.Expr->getFragmentInfo()->OffsetInBits <
- B.Expr->getFragmentInfo()->OffsetInBits;
- });
+ llvm::sort(FrameIndexExprs.begin(), FrameIndexExprs.end(),
+ [](const FrameIndexExpr &A, const FrameIndexExpr &B) -> bool {
+ return A.Expr->getFragmentInfo()->OffsetInBits <
+ B.Expr->getFragmentInfo()->OffsetInBits;
+ });
return FrameIndexExprs;
}
@@ -258,23 +289,34 @@ void DbgVariable::addMMIEntry(const DbgVariable &V) {
"conflicting locations for variable");
}
-static const DwarfAccelTable::Atom TypeAtoms[] = {
- DwarfAccelTable::Atom(dwarf::DW_ATOM_die_offset, dwarf::DW_FORM_data4),
- DwarfAccelTable::Atom(dwarf::DW_ATOM_die_tag, dwarf::DW_FORM_data2),
- DwarfAccelTable::Atom(dwarf::DW_ATOM_type_flags, dwarf::DW_FORM_data1)};
+static AccelTableKind computeAccelTableKind(unsigned DwarfVersion,
+ bool GenerateTypeUnits,
+ DebuggerKind Tuning,
+ const Triple &TT) {
+ // Honor an explicit request.
+ if (AccelTables != AccelTableKind::Default)
+ return AccelTables;
+
+ // Accelerator tables with type units are currently not supported.
+ if (GenerateTypeUnits)
+ return AccelTableKind::None;
+
+ // Accelerator tables get emitted if targetting DWARF v5 or LLDB. DWARF v5
+ // always implies debug_names. For lower standard versions we use apple
+ // accelerator tables on apple platforms and debug_names elsewhere.
+ if (DwarfVersion >= 5)
+ return AccelTableKind::Dwarf;
+ if (Tuning == DebuggerKind::LLDB)
+ return TT.isOSBinFormatMachO() ? AccelTableKind::Apple
+ : AccelTableKind::Dwarf;
+ return AccelTableKind::None;
+}
DwarfDebug::DwarfDebug(AsmPrinter *A, Module *M)
: DebugHandlerBase(A), DebugLocs(A->OutStreamer->isVerboseAsm()),
InfoHolder(A, "info_string", DIEValueAllocator),
SkeletonHolder(A, "skel_string", DIEValueAllocator),
- IsDarwin(A->TM.getTargetTriple().isOSDarwin()),
- AccelNames(DwarfAccelTable::Atom(dwarf::DW_ATOM_die_offset,
- dwarf::DW_FORM_data4)),
- AccelObjC(DwarfAccelTable::Atom(dwarf::DW_ATOM_die_offset,
- dwarf::DW_FORM_data4)),
- AccelNamespace(DwarfAccelTable::Atom(dwarf::DW_ATOM_die_offset,
- dwarf::DW_FORM_data4)),
- AccelTypes(TypeAtoms) {
+ IsDarwin(A->TM.getTargetTriple().isOSDarwin()) {
const Triple &TT = Asm->TM.getTargetTriple();
// Make sure we know our "debugger tuning." The target option takes
@@ -288,11 +330,12 @@ DwarfDebug::DwarfDebug(AsmPrinter *A, Module *M)
else
DebuggerTuning = DebuggerKind::GDB;
- // Turn on accelerator tables for LLDB by default.
- if (DwarfAccelTables == Default)
- HasDwarfAccelTables = tuneForLLDB();
+ if (DwarfInlinedStrings == Default)
+ UseInlineStrings = TT.isNVPTX();
else
- HasDwarfAccelTables = DwarfAccelTables == Enable;
+ UseInlineStrings = DwarfInlinedStrings == Enable;
+
+ UseLocSection = !TT.isNVPTX();
HasAppleExtensionAttributes = tuneForLLDB();
@@ -308,8 +351,23 @@ DwarfDebug::DwarfDebug(AsmPrinter *A, Module *M)
unsigned DwarfVersionNumber = Asm->TM.Options.MCOptions.DwarfVersion;
unsigned DwarfVersion = DwarfVersionNumber ? DwarfVersionNumber
: MMI->getModule()->getDwarfVersion();
- // Use dwarf 4 by default if nothing is requested.
- DwarfVersion = DwarfVersion ? DwarfVersion : dwarf::DWARF_VERSION;
+ // Use dwarf 4 by default if nothing is requested. For NVPTX, use dwarf 2.
+ DwarfVersion =
+ TT.isNVPTX() ? 2 : (DwarfVersion ? DwarfVersion : dwarf::DWARF_VERSION);
+
+ UsePubSections = !NoDwarfPubSections && !TT.isNVPTX();
+ UseRangesSection = !NoDwarfRangesSection && !TT.isNVPTX();
+
+ // Use sections as references. Force for NVPTX.
+ if (DwarfSectionsAsReferences == Default)
+ UseSectionsAsReferences = TT.isNVPTX();
+ else
+ UseSectionsAsReferences = DwarfSectionsAsReferences == Enable;
+
+ GenerateTypeUnits = GenerateDwarfTypeUnits;
+
+ TheAccelTableKind = computeAccelTableKind(
+ DwarfVersion, GenerateTypeUnits, DebuggerTuning, A->TM.getTargetTriple());
// Work around a GDB bug. GDB doesn't support the standard opcode;
// SCE doesn't support GNU's; LLDB prefers the standard opcode, which
@@ -321,6 +379,12 @@ DwarfDebug::DwarfDebug(AsmPrinter *A, Module *M)
// GDB does not fully support the DWARF 4 representation for bitfields.
UseDWARF2Bitfields = (DwarfVersion < 4) || tuneForGDB();
+ // The DWARF v5 string offsets table has - possibly shared - contributions
+ // from each compile and type unit each preceded by a header. The string
+ // offsets table used by the pre-DWARF v5 split-DWARF implementation uses
+ // a monolithic string offsets table without any header.
+ UseSegmentedStringOffsetsTable = DwarfVersion >= 5;
+
Asm->OutStreamer->getContext().setDwarfVersion(DwarfVersion);
}
@@ -355,17 +419,18 @@ static StringRef getObjCMethodName(StringRef In) {
}
// Add the various names to the Dwarf accelerator table names.
-// TODO: Determine whether or not we should add names for programs
-// that do not have a DW_AT_name or DW_AT_linkage_name field - this
-// is only slightly different than the lookup of non-standard ObjC names.
void DwarfDebug::addSubprogramNames(const DISubprogram *SP, DIE &Die) {
if (!SP->isDefinition())
return;
- addAccelName(SP->getName(), Die);
- // If the linkage name is different than the name, go ahead and output
- // that as well into the name table.
- if (SP->getLinkageName() != "" && SP->getName() != SP->getLinkageName())
+ if (SP->getName() != "")
+ addAccelName(SP->getName(), Die);
+
+ // If the linkage name is different than the name, go ahead and output that as
+ // well into the name table. Only do that if we are going to actually emit
+ // that name.
+ if (SP->getLinkageName() != "" && SP->getName() != SP->getLinkageName() &&
+ (useAllLinkageNames() || InfoHolder.getAbstractSPDies().lookup(SP)))
addAccelName(SP->getLinkageName(), Die);
// If this is an Objective-C selector name add it to the ObjC accelerator
@@ -471,8 +536,9 @@ DwarfDebug::getOrCreateDwarfCompileUnit(const DICompileUnit *DIUnit) {
// explicitly describe the directory of all files, never relying on the
// compilation directory.
if (!Asm->OutStreamer->hasRawTextSupport() || SingleCU)
- Asm->OutStreamer->getContext().setMCLineTableCompilationDir(
- NewCU.getUniqueID(), CompilationDir);
+ Asm->OutStreamer->emitDwarfFile0Directive(
+ CompilationDir, FN, NewCU.getMD5AsBytes(DIUnit->getFile()),
+ DIUnit->getSource(), NewCU.getUniqueID());
StringRef Producer = DIUnit->getProducer();
StringRef Flags = DIUnit->getFlags();
@@ -486,6 +552,10 @@ DwarfDebug::getOrCreateDwarfCompileUnit(const DICompileUnit *DIUnit) {
DIUnit->getSourceLanguage());
NewCU.addString(Die, dwarf::DW_AT_name, FN);
+ // Add DW_str_offsets_base to the unit DIE, except for split units.
+ if (useSegmentedStringOffsetsTable() && !useSplitDwarf())
+ NewCU.addStringOffsetsStart();
+
if (!useSplitDwarf()) {
NewCU.initStmtList();
@@ -541,21 +611,22 @@ void DwarfDebug::constructAndAddImportedEntityDIE(DwarfCompileUnit &TheCU,
/// Sort and unique GVEs by comparing their fragment offset.
static SmallVectorImpl<DwarfCompileUnit::GlobalExpr> &
sortGlobalExprs(SmallVectorImpl<DwarfCompileUnit::GlobalExpr> &GVEs) {
- std::sort(GVEs.begin(), GVEs.end(),
- [](DwarfCompileUnit::GlobalExpr A, DwarfCompileUnit::GlobalExpr B) {
- // Sort order: first null exprs, then exprs without fragment
- // info, then sort by fragment offset in bits.
- // FIXME: Come up with a more comprehensive comparator so
- // the sorting isn't non-deterministic, and so the following
- // std::unique call works correctly.
- if (!A.Expr || !B.Expr)
- return !!B.Expr;
- auto FragmentA = A.Expr->getFragmentInfo();
- auto FragmentB = B.Expr->getFragmentInfo();
- if (!FragmentA || !FragmentB)
- return !!FragmentB;
- return FragmentA->OffsetInBits < FragmentB->OffsetInBits;
- });
+ llvm::sort(GVEs.begin(), GVEs.end(),
+ [](DwarfCompileUnit::GlobalExpr A,
+ DwarfCompileUnit::GlobalExpr B) {
+ // Sort order: first null exprs, then exprs without fragment
+ // info, then sort by fragment offset in bits.
+ // FIXME: Come up with a more comprehensive comparator so
+ // the sorting isn't non-deterministic, and so the following
+ // std::unique call works correctly.
+ if (!A.Expr || !B.Expr)
+ return !!B.Expr;
+ auto FragmentA = A.Expr->getFragmentInfo();
+ auto FragmentB = B.Expr->getFragmentInfo();
+ if (!FragmentA || !FragmentB)
+ return !!FragmentB;
+ return FragmentA->OffsetInBits < FragmentB->OffsetInBits;
+ });
GVEs.erase(std::unique(GVEs.begin(), GVEs.end(),
[](DwarfCompileUnit::GlobalExpr A,
DwarfCompileUnit::GlobalExpr B) {
@@ -590,6 +661,19 @@ void DwarfDebug::beginModule() {
GVMap[GVE->getVariable()].push_back({&Global, GVE->getExpression()});
}
+ // Create the symbol that designates the start of the unit's contribution
+ // to the string offsets table. In a split DWARF scenario, only the skeleton
+ // unit has the DW_AT_str_offsets_base attribute (and hence needs the symbol).
+ if (useSegmentedStringOffsetsTable())
+ (useSplitDwarf() ? SkeletonHolder : InfoHolder)
+ .setStringOffsetsStartSym(Asm->createTempSymbol("str_offsets_base"));
+
+ // Create the symbol that designates the start of the DWARF v5 range list
+ // table. It is located past the header and before the offsets table.
+ if (getDwarfVersion() >= 5)
+ (useSplitDwarf() ? SkeletonHolder : InfoHolder)
+ .setRnglistsTableBaseSym(Asm->createTempSymbol("rnglists_table_base"));
+
for (DICompileUnit *CUNode : M->debug_compile_units()) {
// FIXME: Move local imported entities into a list attached to the
// subprogram, then this search won't be needed and a
@@ -694,11 +778,15 @@ void DwarfDebug::finalizeModuleInfo() {
// Emit a unique identifier for this CU.
uint64_t ID =
DIEHash(Asm).computeCUSignature(DWOName, TheCU.getUnitDie());
- TheCU.addUInt(TheCU.getUnitDie(), dwarf::DW_AT_GNU_dwo_id,
- dwarf::DW_FORM_data8, ID);
- SkCU->addUInt(SkCU->getUnitDie(), dwarf::DW_AT_GNU_dwo_id,
- dwarf::DW_FORM_data8, ID);
-
+ if (getDwarfVersion() >= 5) {
+ TheCU.setDWOId(ID);
+ SkCU->setDWOId(ID);
+ } else {
+ TheCU.addUInt(TheCU.getUnitDie(), dwarf::DW_AT_GNU_dwo_id,
+ dwarf::DW_FORM_data8, ID);
+ SkCU->addUInt(SkCU->getUnitDie(), dwarf::DW_AT_GNU_dwo_id,
+ dwarf::DW_FORM_data8, ID);
+ }
// We don't keep track of which addresses are used in which CU so this
// is a bit pessimistic under LTO.
if (!AddrPool.isEmpty()) {
@@ -706,7 +794,7 @@ void DwarfDebug::finalizeModuleInfo() {
SkCU->addSectionLabel(SkCU->getUnitDie(), dwarf::DW_AT_GNU_addr_base,
Sym, Sym);
}
- if (!SkCU->getRangeLists().empty()) {
+ if (getDwarfVersion() < 5 && !SkCU->getRangeLists().empty()) {
const MCSymbol *Sym = TLOF.getDwarfRangesSection()->getBeginSymbol();
SkCU->addSectionLabel(SkCU->getUnitDie(), dwarf::DW_AT_GNU_ranges_base,
Sym, Sym);
@@ -721,7 +809,7 @@ void DwarfDebug::finalizeModuleInfo() {
// ranges for all subprogram DIEs for mach-o.
DwarfCompileUnit &U = SkCU ? *SkCU : TheCU;
if (unsigned NumRanges = TheCU.getRanges().size()) {
- if (NumRanges > 1)
+ if (NumRanges > 1 && useRangesSection())
// A DW_AT_low_pc attribute may also be specified in combination with
// DW_AT_ranges to specify the default base address for use in
// location lists (see Section 2.6.2) and range lists (see Section
@@ -732,6 +820,10 @@ void DwarfDebug::finalizeModuleInfo() {
U.attachRangesOrLowHighPC(U.getUnitDie(), TheCU.takeRanges());
}
+ if (getDwarfVersion() >= 5 && !useSplitDwarf() &&
+ !U.getRangeLists().empty())
+ U.addRnglistsBase();
+
auto *CUNode = cast<DICompileUnit>(P.first);
// If compile Unit has macros, emit "DW_AT_macro_info" attribute.
if (CUNode->getMacros())
@@ -799,11 +891,20 @@ void DwarfDebug::endModule() {
}
// Emit info into the dwarf accelerator table sections.
- if (useDwarfAccelTables()) {
+ switch (getAccelTableKind()) {
+ case AccelTableKind::Apple:
emitAccelNames();
emitAccelObjC();
emitAccelNamespaces();
emitAccelTypes();
+ break;
+ case AccelTableKind::Dwarf:
+ emitAccelDebugNames();
+ break;
+ case AccelTableKind::None:
+ break;
+ case AccelTableKind::Default:
+ llvm_unreachable("Default should have already been resolved.");
}
// Emit the pubnames and pubtypes sections if requested.
@@ -887,7 +988,7 @@ static DebugLocEntry::Value getDebugLocValue(const MachineInstr *MI) {
llvm_unreachable("Unexpected 4-operand DBG_VALUE instruction!");
}
-/// \brief If this and Next are describing different fragments of the same
+/// If this and Next are describing different fragments of the same
/// variable, merge them by appending Next's values to the current
/// list of values.
/// Return true if the merge was successful.
@@ -903,8 +1004,7 @@ bool DebugLocEntry::MergeValues(const DebugLocEntry &Next) {
// sorted.
for (unsigned i = 0, j = 0; i < Values.size(); ++i) {
for (; j < Next.Values.size(); ++j) {
- int res = DebugHandlerBase::fragmentCmp(
- cast<DIExpression>(Values[i].Expression),
+ int res = cast<DIExpression>(Values[i].Expression)->fragmentCmp(
cast<DIExpression>(Next.Values[j].Expression));
if (res == 0) // The two expressions overlap, we can't merge.
return false;
@@ -967,7 +1067,7 @@ DwarfDebug::buildLocationList(SmallVectorImpl<DebugLocEntry> &DebugLoc,
// If this fragment overlaps with any open ranges, truncate them.
const DIExpression *DIExpr = Begin->getDebugExpression();
auto Last = remove_if(OpenRanges, [&](DebugLocEntry::Value R) {
- return fragmentsOverlap(DIExpr, R.getExpression());
+ return DIExpr->fragmentsOverlap(R.getExpression());
});
OpenRanges.erase(Last, OpenRanges.end());
@@ -983,7 +1083,7 @@ DwarfDebug::buildLocationList(SmallVectorImpl<DebugLocEntry> &DebugLoc,
EndLabel = getLabelBeforeInsn(std::next(I)->first);
assert(EndLabel && "Forgot label after instruction ending a range!");
- DEBUG(dbgs() << "DotDebugLoc: " << *Begin << "\n");
+ LLVM_DEBUG(dbgs() << "DotDebugLoc: " << *Begin << "\n");
auto Value = getDebugLocValue(Begin);
DebugLocEntry Loc(StartLabel, EndLabel, Value);
@@ -1012,7 +1112,7 @@ DwarfDebug::buildLocationList(SmallVectorImpl<DebugLocEntry> &DebugLoc,
// Attempt to coalesce the ranges of two otherwise identical
// DebugLocEntries.
auto CurEntry = DebugLoc.rbegin();
- DEBUG({
+ LLVM_DEBUG({
dbgs() << CurEntry->getValues().size() << " Values:\n";
for (auto &Value : CurEntry->getValues())
Value.dump();
@@ -1131,6 +1231,9 @@ void DwarfDebug::collectVariableInfo(DwarfCompileUnit &TheCU,
RegVar->initializeDbgValue(MInsn);
continue;
}
+ // Do not emit location lists if .debug_loc secton is disabled.
+ if (!useLocSection())
+ continue;
// Handle multiple DBG_VALUE instructions describing one variable.
DebugLocStream::ListBuilder List(DebugLocs, TheCU, *Asm, *RegVar, *MInsn);
@@ -1151,10 +1254,12 @@ void DwarfDebug::collectVariableInfo(DwarfCompileUnit &TheCU,
}
// Collect info for variables that were optimized out.
- for (const DILocalVariable *DV : SP->getVariables()) {
- if (Processed.insert(InlinedVariable(DV, nullptr)).second)
- if (LexicalScope *Scope = LScopes.findLexicalScope(DV->getScope()))
- createConcreteVariable(TheCU, *Scope, InlinedVariable(DV, nullptr));
+ for (const DINode *DN : SP->getRetainedNodes()) {
+ if (auto *DV = dyn_cast<DILocalVariable>(DN)) {
+ if (Processed.insert(InlinedVariable(DV, nullptr)).second)
+ if (LexicalScope *Scope = LScopes.findLexicalScope(DV->getScope()))
+ createConcreteVariable(TheCU, *Scope, InlinedVariable(DV, nullptr));
+ }
}
}
@@ -1168,7 +1273,9 @@ void DwarfDebug::beginInstruction(const MachineInstr *MI) {
return;
// Check if source location changes, but ignore DBG_VALUE and CFI locations.
- if (MI->isMetaInstruction())
+ // If the instruction is part of the function frame setup code, do not emit
+ // any line record, as there is no correspondence with any user code.
+ if (MI->isMetaInstruction() || MI->getFlag(MachineInstr::FrameSetup))
return;
const DebugLoc &DL = MI->getDebugLoc();
// When we emit a line-0 record, we don't update PrevInstLoc; so look at
@@ -1333,14 +1440,16 @@ void DwarfDebug::endFunctionImpl(const MachineFunction *MF) {
// Construct abstract scopes.
for (LexicalScope *AScope : LScopes.getAbstractScopesList()) {
auto *SP = cast<DISubprogram>(AScope->getScopeNode());
- // Collect info for variables that were optimized out.
- for (const DILocalVariable *DV : SP->getVariables()) {
- if (!ProcessedVars.insert(InlinedVariable(DV, nullptr)).second)
- continue;
- ensureAbstractVariableIsCreated(TheCU, InlinedVariable(DV, nullptr),
- DV->getScope());
- assert(LScopes.getAbstractScopesList().size() == NumAbstractScopes
- && "ensureAbstractVariableIsCreated inserted abstract scopes");
+ for (const DINode *DN : SP->getRetainedNodes()) {
+ if (auto *DV = dyn_cast<DILocalVariable>(DN)) {
+ // Collect info for variables that were optimized out.
+ if (!ProcessedVars.insert(InlinedVariable(DV, nullptr)).second)
+ continue;
+ ensureAbstractVariableIsCreated(TheCU, InlinedVariable(DV, nullptr),
+ DV->getScope());
+ assert(LScopes.getAbstractScopesList().size() == NumAbstractScopes
+ && "ensureAbstractVariableIsCreated inserted abstract scopes");
+ }
}
constructAbstractSubprogramScopeDIE(TheCU, AScope);
}
@@ -1366,21 +1475,19 @@ void DwarfDebug::endFunctionImpl(const MachineFunction *MF) {
void DwarfDebug::recordSourceLine(unsigned Line, unsigned Col, const MDNode *S,
unsigned Flags) {
StringRef Fn;
- StringRef Dir;
- unsigned Src = 1;
+ unsigned FileNo = 1;
unsigned Discriminator = 0;
if (auto *Scope = cast_or_null<DIScope>(S)) {
Fn = Scope->getFilename();
- Dir = Scope->getDirectory();
if (Line != 0 && getDwarfVersion() >= 4)
if (auto *LBF = dyn_cast<DILexicalBlockFile>(Scope))
Discriminator = LBF->getDiscriminator();
unsigned CUID = Asm->OutStreamer->getContext().getDwarfCompileUnitID();
- Src = static_cast<DwarfCompileUnit &>(*InfoHolder.getUnits()[CUID])
- .getOrCreateSourceID(Fn, Dir);
+ FileNo = static_cast<DwarfCompileUnit &>(*InfoHolder.getUnits()[CUID])
+ .getOrCreateSourceID(Scope->getFile());
}
- Asm->OutStreamer->EmitDwarfLocDirective(Src, Line, Col, Flags, 0,
+ Asm->OutStreamer->EmitDwarfLocDirective(FileNo, Line, Col, Flags, 0,
Discriminator, Fn);
}
@@ -1401,13 +1508,30 @@ void DwarfDebug::emitAbbreviations() {
Holder.emitAbbrevs(Asm->getObjFileLowering().getDwarfAbbrevSection());
}
-void DwarfDebug::emitAccel(DwarfAccelTable &Accel, MCSection *Section,
+void DwarfDebug::emitStringOffsetsTableHeader() {
+ DwarfFile &Holder = useSplitDwarf() ? SkeletonHolder : InfoHolder;
+ Holder.getStringPool().emitStringOffsetsTableHeader(
+ *Asm, Asm->getObjFileLowering().getDwarfStrOffSection(),
+ Holder.getStringOffsetsStartSym());
+}
+
+template <typename AccelTableT>
+void DwarfDebug::emitAccel(AccelTableT &Accel, MCSection *Section,
StringRef TableName) {
- Accel.FinalizeTable(Asm, TableName);
Asm->OutStreamer->SwitchSection(Section);
// Emit the full data.
- Accel.emit(Asm, Section->getBeginSymbol(), this);
+ emitAppleAccelTable(Asm, Accel, TableName, Section->getBeginSymbol());
+}
+
+void DwarfDebug::emitAccelDebugNames() {
+ // Don't emit anything if we have no compilation units to index.
+ if (getUnits().empty())
+ return;
+
+ Asm->OutStreamer->SwitchSection(
+ Asm->getObjFileLowering().getDwarfDebugNamesSection());
+ emitDWARF5AccelTable(Asm, AccelDebugNames, *this, getUnits());
}
// Emit visible names into a hashed accelerator table section.
@@ -1525,6 +1649,14 @@ void DwarfDebug::emitDebugPubSections() {
}
}
+void DwarfDebug::emitSectionReference(const DwarfCompileUnit &CU) {
+ if (useSectionsAsReferences())
+ Asm->EmitDwarfOffset(CU.getSection()->getBeginSymbol(),
+ CU.getDebugSectionOffset());
+ else
+ Asm->emitDwarfSymbolReference(CU.getLabelBegin());
+}
+
void DwarfDebug::emitDebugPubSection(bool GnuStyle, StringRef Name,
DwarfCompileUnit *TheU,
const StringMap<const DIE *> &Globals) {
@@ -1540,13 +1672,13 @@ void DwarfDebug::emitDebugPubSection(bool GnuStyle, StringRef Name,
Asm->OutStreamer->EmitLabel(BeginLabel);
Asm->OutStreamer->AddComment("DWARF Version");
- Asm->EmitInt16(dwarf::DW_PUBNAMES_VERSION);
+ Asm->emitInt16(dwarf::DW_PUBNAMES_VERSION);
Asm->OutStreamer->AddComment("Offset of Compilation Unit Info");
- Asm->emitDwarfSymbolReference(TheU->getLabelBegin());
+ emitSectionReference(*TheU);
Asm->OutStreamer->AddComment("Compilation Unit Length");
- Asm->EmitInt32(TheU->getLength());
+ Asm->emitInt32(TheU->getLength());
// Emit the pubnames for this compilation unit.
for (const auto &GI : Globals) {
@@ -1554,14 +1686,14 @@ void DwarfDebug::emitDebugPubSection(bool GnuStyle, StringRef Name,
const DIE *Entity = GI.second;
Asm->OutStreamer->AddComment("DIE offset");
- Asm->EmitInt32(Entity->getOffset());
+ Asm->emitInt32(Entity->getOffset());
if (GnuStyle) {
dwarf::PubIndexEntryDescriptor Desc = computeIndexValue(TheU, Entity);
Asm->OutStreamer->AddComment(
Twine("Kind: ") + dwarf::GDBIndexEntryKindString(Desc.Kind) + ", " +
dwarf::GDBIndexEntryLinkageString(Desc.Linkage));
- Asm->EmitInt8(Desc.toBits());
+ Asm->emitInt8(Desc.toBits());
}
Asm->OutStreamer->AddComment("External Name");
@@ -1569,14 +1701,20 @@ void DwarfDebug::emitDebugPubSection(bool GnuStyle, StringRef Name,
}
Asm->OutStreamer->AddComment("End Mark");
- Asm->EmitInt32(0);
+ Asm->emitInt32(0);
Asm->OutStreamer->EmitLabel(EndLabel);
}
/// Emit null-terminated strings into a debug str section.
void DwarfDebug::emitDebugStr() {
+ MCSection *StringOffsetsSection = nullptr;
+ if (useSegmentedStringOffsetsTable()) {
+ emitStringOffsetsTableHeader();
+ StringOffsetsSection = Asm->getObjFileLowering().getDwarfStrOffSection();
+ }
DwarfFile &Holder = useSplitDwarf() ? SkeletonHolder : InfoHolder;
- Holder.emitStrings(Asm->getObjFileLowering().getDwarfStrSection());
+ Holder.emitStrings(Asm->getObjFileLowering().getDwarfStrSection(),
+ StringOffsetsSection, /* UseRelativeOffsets = */ true);
}
void DwarfDebug::emitDebugLocEntry(ByteStreamer &Streamer,
@@ -1589,7 +1727,6 @@ void DwarfDebug::emitDebugLocEntry(ByteStreamer &Streamer,
}
static void emitDebugLocValue(const AsmPrinter &AP, const DIBasicType *BT,
- ByteStreamer &Streamer,
const DebugLocEntry::Value &Value,
DwarfExpression &DwarfExpr) {
auto *DIExpr = Value.getExpression();
@@ -1634,11 +1771,11 @@ void DebugLocEntry::finalize(const AsmPrinter &AP,
"fragments are expected to be sorted");
for (auto Fragment : Values)
- emitDebugLocValue(AP, BT, Streamer, Fragment, DwarfExpr);
+ emitDebugLocValue(AP, BT, Fragment, DwarfExpr);
} else {
assert(Values.size() == 1 && "only fragments may have >1 value");
- emitDebugLocValue(AP, BT, Streamer, Value, DwarfExpr);
+ emitDebugLocValue(AP, BT, Value, DwarfExpr);
}
DwarfExpr.finalize();
}
@@ -1646,7 +1783,7 @@ void DebugLocEntry::finalize(const AsmPrinter &AP,
void DwarfDebug::emitDebugLocEntryLocation(const DebugLocStream::Entry &Entry) {
// Emit the size.
Asm->OutStreamer->AddComment("Loc expr size");
- Asm->EmitInt16(DebugLocs.getBytes(Entry).size());
+ Asm->emitInt16(DebugLocs.getBytes(Entry).size());
// Emit the entry.
APByteStreamer Streamer(*Asm);
@@ -1694,14 +1831,14 @@ void DwarfDebug::emitDebugLocDWO() {
// rather than two. We could get fancier and try to, say, reuse an
// address we know we've emitted elsewhere (the start of the function?
// The start of the CU or CU subrange that encloses this range?)
- Asm->EmitInt8(dwarf::DW_LLE_startx_length);
+ Asm->emitInt8(dwarf::DW_LLE_startx_length);
unsigned idx = AddrPool.getIndex(Entry.BeginSym);
Asm->EmitULEB128(idx);
Asm->EmitLabelDifference(Entry.EndSym, Entry.BeginSym, 4);
emitDebugLocEntryLocation(Entry);
}
- Asm->EmitInt8(dwarf::DW_LLE_end_of_list);
+ Asm->emitInt8(dwarf::DW_LLE_end_of_list);
}
}
@@ -1752,7 +1889,7 @@ void DwarfDebug::emitDebugARanges() {
}
// Sort the symbols by offset within the section.
- std::sort(
+ std::stable_sort(
List.begin(), List.end(), [&](const SymbolCU &A, const SymbolCU &B) {
unsigned IA = A.Sym ? Asm->OutStreamer->GetSymbolOrder(A.Sym) : 0;
unsigned IB = B.Sym ? Asm->OutStreamer->GetSymbolOrder(B.Sym) : 0;
@@ -1801,10 +1938,10 @@ void DwarfDebug::emitDebugARanges() {
}
// Sort the CU list (again, to ensure consistent output order).
- std::sort(CUs.begin(), CUs.end(),
- [](const DwarfCompileUnit *A, const DwarfCompileUnit *B) {
- return A->getUniqueID() < B->getUniqueID();
- });
+ llvm::sort(CUs.begin(), CUs.end(),
+ [](const DwarfCompileUnit *A, const DwarfCompileUnit *B) {
+ return A->getUniqueID() < B->getUniqueID();
+ });
// Emit an arange table for each CU we used.
for (DwarfCompileUnit *CU : CUs) {
@@ -1832,15 +1969,15 @@ void DwarfDebug::emitDebugARanges() {
// For each compile unit, write the list of spans it covers.
Asm->OutStreamer->AddComment("Length of ARange Set");
- Asm->EmitInt32(ContentSize);
+ Asm->emitInt32(ContentSize);
Asm->OutStreamer->AddComment("DWARF Arange version number");
- Asm->EmitInt16(dwarf::DW_ARANGES_VERSION);
+ Asm->emitInt16(dwarf::DW_ARANGES_VERSION);
Asm->OutStreamer->AddComment("Offset Into Debug Info Section");
- Asm->emitDwarfSymbolReference(CU->getLabelBegin());
+ emitSectionReference(*CU);
Asm->OutStreamer->AddComment("Address Size (in bytes)");
- Asm->EmitInt8(PtrSize);
+ Asm->emitInt8(PtrSize);
Asm->OutStreamer->AddComment("Segment Size (in bytes)");
- Asm->EmitInt8(0);
+ Asm->emitInt8(0);
Asm->OutStreamer->emitFill(Padding, 0xff);
@@ -1867,17 +2004,151 @@ void DwarfDebug::emitDebugARanges() {
}
}
-/// Emit address ranges into a debug ranges section.
+/// Emit a single range list. We handle both DWARF v5 and earlier.
+static void emitRangeList(AsmPrinter *Asm, DwarfCompileUnit *CU,
+ const RangeSpanList &List) {
+
+ auto DwarfVersion = CU->getDwarfVersion();
+ // Emit our symbol so we can find the beginning of the range.
+ Asm->OutStreamer->EmitLabel(List.getSym());
+ // Gather all the ranges that apply to the same section so they can share
+ // a base address entry.
+ MapVector<const MCSection *, std::vector<const RangeSpan *>> SectionRanges;
+ // Size for our labels.
+ auto Size = Asm->MAI->getCodePointerSize();
+
+ for (const RangeSpan &Range : List.getRanges())
+ SectionRanges[&Range.getStart()->getSection()].push_back(&Range);
+
+ auto *CUBase = CU->getBaseAddress();
+ bool BaseIsSet = false;
+ for (const auto &P : SectionRanges) {
+ // Don't bother with a base address entry if there's only one range in
+ // this section in this range list - for example ranges for a CU will
+ // usually consist of single regions from each of many sections
+ // (-ffunction-sections, or just C++ inline functions) except under LTO
+ // or optnone where there may be holes in a single CU's section
+ // contributions.
+ auto *Base = CUBase;
+ if (!Base && P.second.size() > 1 &&
+ (UseDwarfRangesBaseAddressSpecifier || DwarfVersion >= 5)) {
+ BaseIsSet = true;
+ // FIXME/use care: This may not be a useful base address if it's not
+ // the lowest address/range in this object.
+ Base = P.second.front()->getStart();
+ if (DwarfVersion >= 5) {
+ Asm->OutStreamer->AddComment("DW_RLE_base_address");
+ Asm->OutStreamer->EmitIntValue(dwarf::DW_RLE_base_address, 1);
+ } else
+ Asm->OutStreamer->EmitIntValue(-1, Size);
+ Asm->OutStreamer->AddComment(" base address");
+ Asm->OutStreamer->EmitSymbolValue(Base, Size);
+ } else if (BaseIsSet && DwarfVersion < 5) {
+ BaseIsSet = false;
+ assert(!Base);
+ Asm->OutStreamer->EmitIntValue(-1, Size);
+ Asm->OutStreamer->EmitIntValue(0, Size);
+ }
+
+ for (const auto *RS : P.second) {
+ const MCSymbol *Begin = RS->getStart();
+ const MCSymbol *End = RS->getEnd();
+ assert(Begin && "Range without a begin symbol?");
+ assert(End && "Range without an end symbol?");
+ if (Base) {
+ if (DwarfVersion >= 5) {
+ // Emit DW_RLE_offset_pair when we have a base.
+ Asm->OutStreamer->AddComment("DW_RLE_offset_pair");
+ Asm->OutStreamer->EmitIntValue(dwarf::DW_RLE_offset_pair, 1);
+ Asm->OutStreamer->AddComment(" starting offset");
+ Asm->EmitLabelDifferenceAsULEB128(Begin, Base);
+ Asm->OutStreamer->AddComment(" ending offset");
+ Asm->EmitLabelDifferenceAsULEB128(End, Base);
+ } else {
+ Asm->EmitLabelDifference(Begin, Base, Size);
+ Asm->EmitLabelDifference(End, Base, Size);
+ }
+ } else if (DwarfVersion >= 5) {
+ Asm->OutStreamer->AddComment("DW_RLE_start_length");
+ Asm->OutStreamer->EmitIntValue(dwarf::DW_RLE_start_length, 1);
+ Asm->OutStreamer->AddComment(" start");
+ Asm->OutStreamer->EmitSymbolValue(Begin, Size);
+ Asm->OutStreamer->AddComment(" length");
+ Asm->EmitLabelDifferenceAsULEB128(End, Begin);
+ } else {
+ Asm->OutStreamer->EmitSymbolValue(Begin, Size);
+ Asm->OutStreamer->EmitSymbolValue(End, Size);
+ }
+ }
+ }
+ if (DwarfVersion >= 5) {
+ Asm->OutStreamer->AddComment("DW_RLE_end_of_list");
+ Asm->OutStreamer->EmitIntValue(dwarf::DW_RLE_end_of_list, 1);
+ } else {
+ // Terminate the list with two 0 values.
+ Asm->OutStreamer->EmitIntValue(0, Size);
+ Asm->OutStreamer->EmitIntValue(0, Size);
+ }
+}
+
+// Emit the header of a DWARF 5 range list table. Returns the symbol that
+// designates the end of the table for the caller to emit when the table is
+// complete.
+static MCSymbol *emitRnglistsTableHeader(AsmPrinter *Asm, DwarfFile &Holder) {
+ // The length is described by a starting label right after the length field
+ // and an end label.
+ MCSymbol *TableStart = Asm->createTempSymbol("debug_rnglist_table_start");
+ MCSymbol *TableEnd = Asm->createTempSymbol("debug_rnglist_table_end");
+ // Build the range table header, which starts with the length field.
+ Asm->EmitLabelDifference(TableEnd, TableStart, 4);
+ Asm->OutStreamer->EmitLabel(TableStart);
+ // Version number (DWARF v5 and later).
+ Asm->emitInt16(Asm->OutStreamer->getContext().getDwarfVersion());
+ // Address size.
+ Asm->emitInt8(Asm->MAI->getCodePointerSize());
+ // Segment selector size.
+ Asm->emitInt8(0);
+
+ MCSymbol *RnglistTableBaseSym = Holder.getRnglistsTableBaseSym();
+
+ // FIXME: Generate the offsets table and use DW_FORM_rnglistx with the
+ // DW_AT_ranges attribute. Until then set the number of offsets to 0.
+ Asm->emitInt32(0);
+ Asm->OutStreamer->EmitLabel(RnglistTableBaseSym);
+ return TableEnd;
+}
+
+/// Emit address ranges into the .debug_ranges section or into the DWARF v5
+/// .debug_rnglists section.
void DwarfDebug::emitDebugRanges() {
if (CUMap.empty())
return;
- // Start the dwarf ranges section.
- Asm->OutStreamer->SwitchSection(
- Asm->getObjFileLowering().getDwarfRangesSection());
+ auto NoRangesPresent = [this]() {
+ return llvm::all_of(
+ CUMap, [](const decltype(CUMap)::const_iterator::value_type &Pair) {
+ return Pair.second->getRangeLists().empty();
+ });
+ };
- // Size for our labels.
- unsigned char Size = Asm->MAI->getCodePointerSize();
+ if (!useRangesSection()) {
+ assert(NoRangesPresent() && "No debug ranges expected.");
+ return;
+ }
+
+ if (getDwarfVersion() >= 5 && NoRangesPresent())
+ return;
+
+ // Start the dwarf ranges section.
+ MCSymbol *TableEnd = nullptr;
+ if (getDwarfVersion() >= 5) {
+ Asm->OutStreamer->SwitchSection(
+ Asm->getObjFileLowering().getDwarfRnglistsSection());
+ TableEnd = emitRnglistsTableHeader(Asm, useSplitDwarf() ? SkeletonHolder
+ : InfoHolder);
+ } else
+ Asm->OutStreamer->SwitchSection(
+ Asm->getObjFileLowering().getDwarfRangesSection());
// Grab the specific ranges for the compile units in the module.
for (const auto &I : CUMap) {
@@ -1887,61 +2158,12 @@ void DwarfDebug::emitDebugRanges() {
TheCU = Skel;
// Iterate over the misc ranges for the compile units in the module.
- for (const RangeSpanList &List : TheCU->getRangeLists()) {
- // Emit our symbol so we can find the beginning of the range.
- Asm->OutStreamer->EmitLabel(List.getSym());
-
- // Gather all the ranges that apply to the same section so they can share
- // a base address entry.
- MapVector<const MCSection *, std::vector<const RangeSpan *>> MV;
- for (const RangeSpan &Range : List.getRanges()) {
- MV[&Range.getStart()->getSection()].push_back(&Range);
- }
-
- auto *CUBase = TheCU->getBaseAddress();
- bool BaseIsSet = false;
- for (const auto &P : MV) {
- // Don't bother with a base address entry if there's only one range in
- // this section in this range list - for example ranges for a CU will
- // usually consist of single regions from each of many sections
- // (-ffunction-sections, or just C++ inline functions) except under LTO
- // or optnone where there may be holes in a single CU's section
- // contrubutions.
- auto *Base = CUBase;
- if (!Base && P.second.size() > 1 &&
- UseDwarfRangesBaseAddressSpecifier) {
- BaseIsSet = true;
- // FIXME/use care: This may not be a useful base address if it's not
- // the lowest address/range in this object.
- Base = P.second.front()->getStart();
- Asm->OutStreamer->EmitIntValue(-1, Size);
- Asm->OutStreamer->EmitSymbolValue(Base, Size);
- } else if (BaseIsSet) {
- BaseIsSet = false;
- Asm->OutStreamer->EmitIntValue(-1, Size);
- Asm->OutStreamer->EmitIntValue(0, Size);
- }
-
- for (const auto *RS : P.second) {
- const MCSymbol *Begin = RS->getStart();
- const MCSymbol *End = RS->getEnd();
- assert(Begin && "Range without a begin symbol?");
- assert(End && "Range without an end symbol?");
- if (Base) {
- Asm->EmitLabelDifference(Begin, Base, Size);
- Asm->EmitLabelDifference(End, Base, Size);
- } else {
- Asm->OutStreamer->EmitSymbolValue(Begin, Size);
- Asm->OutStreamer->EmitSymbolValue(End, Size);
- }
- }
- }
-
- // And terminate the list with two 0 values.
- Asm->OutStreamer->EmitIntValue(0, Size);
- Asm->OutStreamer->EmitIntValue(0, Size);
- }
+ for (const RangeSpanList &List : TheCU->getRangeLists())
+ emitRangeList(Asm, TheCU, List);
}
+
+ if (TableEnd)
+ Asm->OutStreamer->EmitLabel(TableEnd);
}
void DwarfDebug::handleMacroNodes(DIMacroNodeArray Nodes, DwarfCompileUnit &U) {
@@ -1963,20 +2185,17 @@ void DwarfDebug::emitMacro(DIMacro &M) {
Asm->OutStreamer->EmitBytes(Name);
if (!Value.empty()) {
// There should be one space between macro name and macro value.
- Asm->EmitInt8(' ');
+ Asm->emitInt8(' ');
Asm->OutStreamer->EmitBytes(Value);
}
- Asm->EmitInt8('\0');
+ Asm->emitInt8('\0');
}
void DwarfDebug::emitMacroFile(DIMacroFile &F, DwarfCompileUnit &U) {
assert(F.getMacinfoType() == dwarf::DW_MACINFO_start_file);
Asm->EmitULEB128(dwarf::DW_MACINFO_start_file);
Asm->EmitULEB128(F.getLine());
- DIFile *File = F.getFile();
- unsigned FID =
- U.getOrCreateSourceID(File->getFilename(), File->getDirectory());
- Asm->EmitULEB128(FID);
+ Asm->EmitULEB128(U.getOrCreateSourceID(F.getFile()));
handleMacroNodes(F.getElements(), U);
Asm->EmitULEB128(dwarf::DW_MACINFO_end_file);
}
@@ -1995,11 +2214,14 @@ void DwarfDebug::emitDebugMacinfo() {
auto *SkCU = TheCU.getSkeleton();
DwarfCompileUnit &U = SkCU ? *SkCU : TheCU;
auto *CUNode = cast<DICompileUnit>(P.first);
- Asm->OutStreamer->EmitLabel(U.getMacroLabelBegin());
- handleMacroNodes(CUNode->getMacros(), U);
+ DIMacroNodeArray Macros = CUNode->getMacros();
+ if (!Macros.empty()) {
+ Asm->OutStreamer->EmitLabel(U.getMacroLabelBegin());
+ handleMacroNodes(Macros, U);
+ }
}
Asm->OutStreamer->AddComment("End Of Macro List Mark");
- Asm->EmitInt8(0);
+ Asm->emitInt8(0);
}
// DWARF5 Experimental Separate Dwarf emitters.
@@ -2017,9 +2239,6 @@ void DwarfDebug::initSkeletonUnit(const DwarfUnit &U, DIE &Die,
SkeletonHolder.addUnit(std::move(NewU));
}
-// This DIE has the following attributes: DW_AT_comp_dir, DW_AT_stmt_list,
-// DW_AT_low_pc, DW_AT_high_pc, DW_AT_ranges, DW_AT_dwo_name, DW_AT_dwo_id,
-// DW_AT_addr_base, DW_AT_ranges_base.
DwarfCompileUnit &DwarfDebug::constructSkeletonCU(const DwarfCompileUnit &CU) {
auto OwnedUnit = llvm::make_unique<DwarfCompileUnit>(
@@ -2029,6 +2248,9 @@ DwarfCompileUnit &DwarfDebug::constructSkeletonCU(const DwarfCompileUnit &CU) {
NewCU.initStmtList();
+ if (useSegmentedStringOffsetsTable())
+ NewCU.addStringOffsetsStart();
+
initSkeletonUnit(CU, NewCU.getUnitDie(), std::move(OwnedUnit));
return NewCU;
@@ -2051,26 +2273,37 @@ void DwarfDebug::emitDebugAbbrevDWO() {
void DwarfDebug::emitDebugLineDWO() {
assert(useSplitDwarf() && "No split dwarf?");
- Asm->OutStreamer->SwitchSection(
+ SplitTypeUnitFileTable.Emit(
+ *Asm->OutStreamer, MCDwarfLineTableParams(),
Asm->getObjFileLowering().getDwarfLineDWOSection());
- SplitTypeUnitFileTable.Emit(*Asm->OutStreamer, MCDwarfLineTableParams());
+}
+
+void DwarfDebug::emitStringOffsetsTableHeaderDWO() {
+ assert(useSplitDwarf() && "No split dwarf?");
+ InfoHolder.getStringPool().emitStringOffsetsTableHeader(
+ *Asm, Asm->getObjFileLowering().getDwarfStrOffDWOSection(),
+ InfoHolder.getStringOffsetsStartSym());
}
// Emit the .debug_str.dwo section for separated dwarf. This contains the
// string section and is identical in format to traditional .debug_str
// sections.
void DwarfDebug::emitDebugStrDWO() {
+ if (useSegmentedStringOffsetsTable())
+ emitStringOffsetsTableHeaderDWO();
assert(useSplitDwarf() && "No split dwarf?");
MCSection *OffSec = Asm->getObjFileLowering().getDwarfStrOffDWOSection();
InfoHolder.emitStrings(Asm->getObjFileLowering().getDwarfStrDWOSection(),
- OffSec);
+ OffSec, /* UseRelativeOffsets = */ false);
}
MCDwarfDwoLineTable *DwarfDebug::getDwoLineTable(const DwarfCompileUnit &CU) {
if (!useSplitDwarf())
return nullptr;
- if (SingleCU)
- SplitTypeUnitFileTable.setCompilationDir(CU.getCUNode()->getDirectory());
+ const DICompileUnit *DIUnit = CU.getCUNode();
+ SplitTypeUnitFileTable.maybeSetRootFile(
+ DIUnit->getDirectory(), DIUnit->getFilename(),
+ CU.getMD5AsBytes(DIUnit->getFile()), DIUnit->getSource());
return &SplitTypeUnitFileTable;
}
@@ -2119,10 +2352,16 @@ void DwarfDebug::addDwarfTypeUnitType(DwarfCompileUnit &CU,
if (useSplitDwarf())
NewTU.setSection(Asm->getObjFileLowering().getDwarfTypesDWOSection());
else {
- CU.applyStmtList(UnitDie);
NewTU.setSection(Asm->getObjFileLowering().getDwarfTypesSection(Signature));
+ // Non-split type units reuse the compile unit's line table.
+ CU.applyStmtList(UnitDie);
}
+ // Add DW_AT_str_offsets_base to the type unit DIE, but not for split type
+ // units.
+ if (useSegmentedStringOffsetsTable() && !useSplitDwarf())
+ NewTU.addStringOffsetsStart();
+
NewTU.setType(NewTU.createTypeDIE(CTy));
if (TopLevelType) {
@@ -2157,32 +2396,50 @@ void DwarfDebug::addDwarfTypeUnitType(DwarfCompileUnit &CU,
CU.addDIETypeSignature(RefDie, Signature);
}
-// Accelerator table mutators - add each name along with its companion
-// DIE to the proper table while ensuring that the name that we're going
-// to reference is in the string table. We do this since the names we
-// add may not only be identical to the names in the DIE.
-void DwarfDebug::addAccelName(StringRef Name, const DIE &Die) {
- if (!useDwarfAccelTables())
+// Add the Name along with its companion DIE to the appropriate accelerator
+// table (for AccelTableKind::Dwarf it's always AccelDebugNames, for
+// AccelTableKind::Apple, we use the table we got as an argument). If
+// accelerator tables are disabled, this function does nothing.
+template <typename DataT>
+void DwarfDebug::addAccelNameImpl(AccelTable<DataT> &AppleAccel, StringRef Name,
+ const DIE &Die) {
+ if (getAccelTableKind() == AccelTableKind::None)
return;
- AccelNames.AddName(InfoHolder.getStringPool().getEntry(*Asm, Name), &Die);
+
+ DwarfFile &Holder = useSplitDwarf() ? SkeletonHolder : InfoHolder;
+ DwarfStringPoolEntryRef Ref =
+ Holder.getStringPool().getEntry(*Asm, Name);
+
+ switch (getAccelTableKind()) {
+ case AccelTableKind::Apple:
+ AppleAccel.addName(Ref, Die);
+ break;
+ case AccelTableKind::Dwarf:
+ AccelDebugNames.addName(Ref, Die);
+ break;
+ case AccelTableKind::Default:
+ llvm_unreachable("Default should have already been resolved.");
+ case AccelTableKind::None:
+ llvm_unreachable("None handled above");
+ }
+}
+
+void DwarfDebug::addAccelName(StringRef Name, const DIE &Die) {
+ addAccelNameImpl(AccelNames, Name, Die);
}
void DwarfDebug::addAccelObjC(StringRef Name, const DIE &Die) {
- if (!useDwarfAccelTables())
- return;
- AccelObjC.AddName(InfoHolder.getStringPool().getEntry(*Asm, Name), &Die);
+ // ObjC names go only into the Apple accelerator tables.
+ if (getAccelTableKind() == AccelTableKind::Apple)
+ addAccelNameImpl(AccelObjC, Name, Die);
}
void DwarfDebug::addAccelNamespace(StringRef Name, const DIE &Die) {
- if (!useDwarfAccelTables())
- return;
- AccelNamespace.AddName(InfoHolder.getStringPool().getEntry(*Asm, Name), &Die);
+ addAccelNameImpl(AccelNamespace, Name, Die);
}
void DwarfDebug::addAccelType(StringRef Name, const DIE &Die, char Flags) {
- if (!useDwarfAccelTables())
- return;
- AccelTypes.AddName(InfoHolder.getStringPool().getEntry(*Asm, Name), &Die);
+ addAccelNameImpl(AccelTypes, Name, Die);
}
uint16_t DwarfDebug::getDwarfVersion() const {
diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.h b/lib/CodeGen/AsmPrinter/DwarfDebug.h
index 2ae0b418a91e..0c7be5d27dfe 100644
--- a/lib/CodeGen/AsmPrinter/DwarfDebug.h
+++ b/lib/CodeGen/AsmPrinter/DwarfDebug.h
@@ -18,7 +18,6 @@
#include "DbgValueHistoryCalculator.h"
#include "DebugHandlerBase.h"
#include "DebugLocStream.h"
-#include "DwarfAccelTable.h"
#include "DwarfFile.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
@@ -31,6 +30,7 @@
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/BinaryFormat/Dwarf.h"
+#include "llvm/CodeGen/AccelTable.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/IR/DebugInfoMetadata.h"
#include "llvm/IR/DebugLoc.h"
@@ -192,6 +192,14 @@ struct SymbolCU {
DwarfCompileUnit *CU;
};
+/// The kind of accelerator tables we should emit.
+enum class AccelTableKind {
+ Default, ///< Platform default.
+ None, ///< None.
+ Apple, ///< .apple_names, .apple_namespaces, .apple_types, .apple_objc.
+ Dwarf, ///< DWARF v5 .debug_names.
+};
+
/// Collects and handles dwarf debug information.
class DwarfDebug : public DebugHandlerBase {
/// All DIEValues are allocated through this allocator.
@@ -255,12 +263,37 @@ class DwarfDebug : public DebugHandlerBase {
/// Whether to emit all linkage names, or just abstract subprograms.
bool UseAllLinkageNames;
+ /// Use inlined strings.
+ bool UseInlineStrings = false;
+
+ /// Whether to emit DWARF pub sections or not.
+ bool UsePubSections = true;
+
+ /// Allow emission of .debug_ranges section.
+ bool UseRangesSection = true;
+
+ /// True if the sections itself must be used as references and don't create
+ /// temp symbols inside DWARF sections.
+ bool UseSectionsAsReferences = false;
+
+ ///Allow emission of the .debug_loc section.
+ bool UseLocSection = true;
+
+ /// Generate DWARF v4 type units.
+ bool GenerateTypeUnits;
+
/// DWARF5 Experimental Options
/// @{
- bool HasDwarfAccelTables;
+ AccelTableKind TheAccelTableKind;
bool HasAppleExtensionAttributes;
bool HasSplitDwarf;
+ /// Whether to generate the DWARF v5 string offsets table.
+ /// It consists of a series of contributions, each preceded by a header.
+ /// The pre-DWARF v5 string offsets table for split dwarf is, in contrast,
+ /// a monolithic sequence of string offsets.
+ bool UseSegmentedStringOffsetsTable;
+
/// Separated Dwarf Variables
/// In general these will all be for bits that are left in the
/// original object file, rather than things that are meant
@@ -283,10 +316,12 @@ class DwarfDebug : public DebugHandlerBase {
AddressPool AddrPool;
- DwarfAccelTable AccelNames;
- DwarfAccelTable AccelObjC;
- DwarfAccelTable AccelNamespace;
- DwarfAccelTable AccelTypes;
+ /// Accelerator tables.
+ AccelTable<DWARF5AccelTableData> AccelDebugNames;
+ AccelTable<AppleAccelTableOffsetData> AccelNames;
+ AccelTable<AppleAccelTableOffsetData> AccelObjC;
+ AccelTable<AppleAccelTableOffsetData> AccelNamespace;
+ AccelTable<AppleAccelTableTypeData> AccelTypes;
// Identify a debugger for "tuning" the debug info.
DebuggerKind DebuggerTuning = DebuggerKind::Default;
@@ -299,9 +334,9 @@ class DwarfDebug : public DebugHandlerBase {
using InlinedVariable = DbgValueHistoryMap::InlinedVariable;
- void ensureAbstractVariableIsCreated(DwarfCompileUnit &CU, InlinedVariable Var,
+ void ensureAbstractVariableIsCreated(DwarfCompileUnit &CU, InlinedVariable IV,
const MDNode *Scope);
- void ensureAbstractVariableIsCreatedIfScoped(DwarfCompileUnit &CU, InlinedVariable Var,
+ void ensureAbstractVariableIsCreatedIfScoped(DwarfCompileUnit &CU, InlinedVariable IV,
const MDNode *Scope);
DbgVariable *createConcreteVariable(DwarfCompileUnit &TheCU,
@@ -310,6 +345,10 @@ class DwarfDebug : public DebugHandlerBase {
/// Construct a DIE for this abstract scope.
void constructAbstractSubprogramScopeDIE(DwarfCompileUnit &SrcCU, LexicalScope *Scope);
+ template <typename DataT>
+ void addAccelNameImpl(AccelTable<DataT> &AppleAccel, StringRef Name,
+ const DIE &Die);
+
void finishVariableDefinitions();
void finishSubprogramDefinitions();
@@ -324,9 +363,15 @@ class DwarfDebug : public DebugHandlerBase {
/// Emit the abbreviation section.
void emitAbbreviations();
+ /// Emit the string offsets table header.
+ void emitStringOffsetsTableHeader();
+
/// Emit a specified accelerator table.
- void emitAccel(DwarfAccelTable &Accel, MCSection *Section,
- StringRef TableName);
+ template <typename AccelTableT>
+ void emitAccel(AccelTableT &Accel, MCSection *Section, StringRef TableName);
+
+ /// Emit DWARF v5 accelerator table.
+ void emitAccelDebugNames();
/// Emit visible names into a hashed accelerator table section.
void emitAccelNames();
@@ -363,6 +408,9 @@ class DwarfDebug : public DebugHandlerBase {
/// Emit address ranges into a debug ranges section.
void emitDebugRanges();
+ /// Emit range lists into a DWARF v5 debug rnglists section.
+ void emitDebugRnglists();
+
/// Emit macros into a debug macinfo section.
void emitDebugMacinfo();
void emitMacro(DIMacro &M);
@@ -375,8 +423,13 @@ class DwarfDebug : public DebugHandlerBase {
void initSkeletonUnit(const DwarfUnit &U, DIE &Die,
std::unique_ptr<DwarfCompileUnit> NewU);
- /// Construct the split debug info compile unit for the debug info
- /// section.
+ /// Construct the split debug info compile unit for the debug info section.
+ /// In DWARF v5, the skeleton unit DIE may have the following attributes:
+ /// DW_AT_addr_base, DW_AT_comp_dir, DW_AT_dwo_name, DW_AT_high_pc,
+ /// DW_AT_low_pc, DW_AT_ranges, DW_AT_stmt_list, and DW_AT_str_offsets_base.
+ /// Prior to DWARF v5 it may also have DW_AT_GNU_dwo_id. DW_AT_GNU_dwo_name
+ /// is used instead of DW_AT_dwo_name, Dw_AT_GNU_addr_base instead of
+ /// DW_AT_addr_base, and DW_AT_GNU_ranges_base instead of DW_AT_rnglists_base.
DwarfCompileUnit &constructSkeletonCU(const DwarfCompileUnit &CU);
/// Emit the debug info dwo section.
@@ -388,6 +441,9 @@ class DwarfDebug : public DebugHandlerBase {
/// Emit the debug line dwo section.
void emitDebugLineDWO();
+ /// Emit the dwo stringoffsets table header.
+ void emitStringOffsetsTableHeaderDWO();
+
/// Emit the debug str dwo section.
void emitDebugStrDWO();
@@ -422,6 +478,9 @@ class DwarfDebug : public DebugHandlerBase {
void collectVariableInfoFromMFTable(DwarfCompileUnit &TheCU,
DenseSet<InlinedVariable> &P);
+ /// Emit the reference to the section.
+ void emitSectionReference(const DwarfCompileUnit &CU);
+
protected:
/// Gather pre-function debug information.
void beginFunctionImpl(const MachineFunction *MF) override;
@@ -478,11 +537,30 @@ public:
/// DWARF4 format.
bool useDWARF2Bitfields() const { return UseDWARF2Bitfields; }
+ /// Returns whether to use inline strings.
+ bool useInlineStrings() const { return UseInlineStrings; }
+
+ /// Returns whether GNU pub sections should be emitted.
+ bool usePubSections() const { return UsePubSections; }
+
+ /// Returns whether ranges section should be emitted.
+ bool useRangesSection() const { return UseRangesSection; }
+
+ /// Returns whether to use sections as labels rather than temp symbols.
+ bool useSectionsAsReferences() const {
+ return UseSectionsAsReferences;
+ }
+
+ /// Returns whether .debug_loc section should be emitted.
+ bool useLocSection() const { return UseLocSection; }
+
+ /// Returns whether to generate DWARF v4 type units.
+ bool generateTypeUnits() const { return GenerateTypeUnits; }
+
// Experimental DWARF5 features.
- /// Returns whether or not to emit tables that dwarf consumers can
- /// use to accelerate lookup.
- bool useDwarfAccelTables() const { return HasDwarfAccelTables; }
+ /// Returns what kind (if any) of accelerator tables to emit.
+ AccelTableKind getAccelTableKind() const { return TheAccelTableKind; }
bool useAppleExtensionAttributes() const {
return HasAppleExtensionAttributes;
@@ -492,6 +570,16 @@ public:
/// split dwarf proposal support.
bool useSplitDwarf() const { return HasSplitDwarf; }
+ /// Returns whether to generate a string offsets table with (possibly shared)
+ /// contributions from each CU and type unit. This implies the use of
+ /// DW_FORM_strx* indirect references with DWARF v5 and beyond. Note that
+ /// DW_FORM_GNU_str_index is also an indirect reference, but it is used with
+ /// a pre-DWARF v5 implementation of split DWARF sections, which uses a
+ /// monolithic string offsets table.
+ bool useSegmentedStringOffsetsTable() const {
+ return UseSegmentedStringOffsetsTable;
+ }
+
bool shareAcrossDWOCUs() const;
/// Returns the Dwarf Version.
@@ -537,6 +625,9 @@ public:
/// Find the matching DwarfCompileUnit for the given CU DIE.
DwarfCompileUnit *lookupCU(const DIE *Die) { return CUDieMap.lookup(Die); }
+ const DwarfCompileUnit *lookupCU(const DIE *Die) const {
+ return CUDieMap.lookup(Die);
+ }
/// \defgroup DebuggerTuning Predicates to tune DWARF for a given debugger.
///
diff --git a/lib/CodeGen/AsmPrinter/DwarfException.h b/lib/CodeGen/AsmPrinter/DwarfException.h
index 80d5bd208ed8..b57ea8fc6322 100644
--- a/lib/CodeGen/AsmPrinter/DwarfException.h
+++ b/lib/CodeGen/AsmPrinter/DwarfException.h
@@ -70,7 +70,7 @@ public:
};
class LLVM_LIBRARY_VISIBILITY ARMException : public DwarfCFIExceptionBase {
- void emitTypeInfos(unsigned TTypeEncoding) override;
+ void emitTypeInfos(unsigned TTypeEncoding, MCSymbol *TTBaseLabel) override;
ARMTargetStreamer &getTargetStreamer();
public:
diff --git a/lib/CodeGen/AsmPrinter/DwarfExpression.cpp b/lib/CodeGen/AsmPrinter/DwarfExpression.cpp
index 68d25fe37b43..d8d1a5e8f841 100644
--- a/lib/CodeGen/AsmPrinter/DwarfExpression.cpp
+++ b/lib/CodeGen/AsmPrinter/DwarfExpression.cpp
@@ -123,7 +123,10 @@ bool DwarfExpression::addMachineReg(const TargetRegisterInfo &TRI,
const TargetRegisterClass *RC = TRI.getMinimalPhysRegClass(MachineReg);
unsigned RegSize = TRI.getRegSizeInBits(*RC);
// Keep track of the bits in the register we already emitted, so we
- // can avoid emitting redundant aliasing subregs.
+ // can avoid emitting redundant aliasing subregs. Because this is
+ // just doing a greedy scan of all subregisters, it is possible that
+ // this doesn't find a combination of subregisters that fully cover
+ // the register (even though one may exist).
SmallBitVector Coverage(RegSize, false);
for (MCSubRegIterator SR(MachineReg, &TRI); SR.isValid(); ++SR) {
unsigned Idx = TRI.getSubRegIndex(MachineReg, *SR);
@@ -143,7 +146,7 @@ bool DwarfExpression::addMachineReg(const TargetRegisterInfo &TRI,
if (CurSubReg.test(Coverage)) {
// Emit a piece for any gap in the coverage.
if (Offset > CurPos)
- DwarfRegs.push_back({-1, Offset - CurPos, nullptr});
+ DwarfRegs.push_back({-1, Offset - CurPos, "no DWARF register encoding"});
DwarfRegs.push_back(
{Reg, std::min<unsigned>(Size, MaxSize - Offset), "sub-register"});
if (Offset >= MaxSize)
@@ -154,8 +157,13 @@ bool DwarfExpression::addMachineReg(const TargetRegisterInfo &TRI,
CurPos = Offset + Size;
}
}
-
- return CurPos;
+ // Failed to find any DWARF encoding.
+ if (CurPos == 0)
+ return false;
+ // Found a partial or complete DWARF encoding.
+ if (CurPos < RegSize)
+ DwarfRegs.push_back({-1, RegSize - CurPos, "no DWARF register encoding"});
+ return true;
}
void DwarfExpression::addStackValue() {
@@ -341,11 +349,22 @@ void DwarfExpression::addExpression(DIExpressionCursor &&ExprCursor,
case dwarf::DW_OP_plus:
case dwarf::DW_OP_minus:
case dwarf::DW_OP_mul:
+ case dwarf::DW_OP_div:
+ case dwarf::DW_OP_mod:
+ case dwarf::DW_OP_or:
+ case dwarf::DW_OP_and:
+ case dwarf::DW_OP_xor:
+ case dwarf::DW_OP_shl:
+ case dwarf::DW_OP_shr:
+ case dwarf::DW_OP_shra:
+ case dwarf::DW_OP_lit0:
+ case dwarf::DW_OP_not:
+ case dwarf::DW_OP_dup:
emitOp(Op->getOp());
break;
case dwarf::DW_OP_deref:
assert(LocationKind != Register);
- if (LocationKind != Memory && isMemoryLocation(ExprCursor))
+ if (LocationKind != Memory && ::isMemoryLocation(ExprCursor))
// Turning this into a memory location description makes the deref
// implicit.
LocationKind = Memory;
diff --git a/lib/CodeGen/AsmPrinter/DwarfExpression.h b/lib/CodeGen/AsmPrinter/DwarfExpression.h
index ea5cbc40ba35..952b0d99a95a 100644
--- a/lib/CodeGen/AsmPrinter/DwarfExpression.h
+++ b/lib/CodeGen/AsmPrinter/DwarfExpression.h
@@ -211,6 +211,9 @@ public:
/// Emit an unsigned constant.
void addUnsignedConstant(const APInt &Value);
+ bool isMemoryLocation() const { return LocationKind == Memory; }
+ bool isUnknownLocation() const { return LocationKind == Unknown; }
+
/// Lock this down to become a memory location description.
void setMemoryLocationKind() {
assert(LocationKind == Unknown);
diff --git a/lib/CodeGen/AsmPrinter/DwarfFile.cpp b/lib/CodeGen/AsmPrinter/DwarfFile.cpp
index 3c04c969192d..c90bd568162d 100644
--- a/lib/CodeGen/AsmPrinter/DwarfFile.cpp
+++ b/lib/CodeGen/AsmPrinter/DwarfFile.cpp
@@ -77,42 +77,24 @@ unsigned DwarfFile::computeSizeAndOffset(DIE &Die, unsigned Offset) {
void DwarfFile::emitAbbrevs(MCSection *Section) { Abbrevs.Emit(Asm, Section); }
// Emit strings into a string section.
-void DwarfFile::emitStrings(MCSection *StrSection, MCSection *OffsetSection) {
- StrPool.emit(*Asm, StrSection, OffsetSection);
+void DwarfFile::emitStrings(MCSection *StrSection, MCSection *OffsetSection,
+ bool UseRelativeOffsets) {
+ StrPool.emit(*Asm, StrSection, OffsetSection, UseRelativeOffsets);
}
bool DwarfFile::addScopeVariable(LexicalScope *LS, DbgVariable *Var) {
- SmallVectorImpl<DbgVariable *> &Vars = ScopeVariables[LS];
+ auto &ScopeVars = ScopeVariables[LS];
const DILocalVariable *DV = Var->getVariable();
- // Variables with positive arg numbers are parameters.
if (unsigned ArgNum = DV->getArg()) {
- // Keep all parameters in order at the start of the variable list to ensure
- // function types are correct (no out-of-order parameters)
- //
- // This could be improved by only doing it for optimized builds (unoptimized
- // builds have the right order to begin with), searching from the back (this
- // would catch the unoptimized case quickly), or doing a binary search
- // rather than linear search.
- auto I = Vars.begin();
- while (I != Vars.end()) {
- unsigned CurNum = (*I)->getVariable()->getArg();
- // A local (non-parameter) variable has been found, insert immediately
- // before it.
- if (CurNum == 0)
- break;
- // A later indexed parameter has been found, insert immediately before it.
- if (CurNum > ArgNum)
- break;
- if (CurNum == ArgNum) {
- (*I)->addMMIEntry(*Var);
- return false;
- }
- ++I;
+ auto Cached = ScopeVars.Args.find(ArgNum);
+ if (Cached == ScopeVars.Args.end())
+ ScopeVars.Args[ArgNum] = Var;
+ else {
+ Cached->second->addMMIEntry(*Var);
+ return false;
}
- Vars.insert(I, Var);
- return true;
- }
-
- Vars.push_back(Var);
+ } else {
+ ScopeVars.Locals.push_back(Var);
+ }
return true;
}
diff --git a/lib/CodeGen/AsmPrinter/DwarfFile.h b/lib/CodeGen/AsmPrinter/DwarfFile.h
index 167ca13c19c1..8dfbc4e1c434 100644
--- a/lib/CodeGen/AsmPrinter/DwarfFile.h
+++ b/lib/CodeGen/AsmPrinter/DwarfFile.h
@@ -17,6 +17,7 @@
#include "llvm/CodeGen/DIE.h"
#include "llvm/IR/Metadata.h"
#include "llvm/Support/Allocator.h"
+#include <map>
#include <memory>
#include <utility>
@@ -43,8 +44,23 @@ class DwarfFile {
DwarfStringPool StrPool;
- // Collection of dbg variables of a scope.
- DenseMap<LexicalScope *, SmallVector<DbgVariable *, 8>> ScopeVariables;
+ /// DWARF v5: The symbol that designates the start of the contribution to
+ /// the string offsets table. The contribution is shared by all units.
+ MCSymbol *StringOffsetsStartSym = nullptr;
+
+ /// DWARF v5: The symbol that designates the base of the range list table.
+ /// The table is shared by all units.
+ MCSymbol *RnglistsTableBaseSym = nullptr;
+
+ /// The variables of a lexical scope.
+ struct ScopeVars {
+ /// We need to sort Args by ArgNo and check for duplicates. This could also
+ /// be implemented as a list or vector + std::lower_bound().
+ std::map<unsigned, DbgVariable *> Args;
+ SmallVector<DbgVariable *, 8> Locals;
+ };
+ /// Collection of DbgVariables of each lexical scope.
+ DenseMap<LexicalScope *, ScopeVars> ScopeVariables;
// Collection of abstract subprogram DIEs.
DenseMap<const MDNode *, DIE *> AbstractSPDies;
@@ -62,39 +78,51 @@ public:
return CUs;
}
- /// \brief Compute the size and offset of a DIE given an incoming Offset.
+ /// Compute the size and offset of a DIE given an incoming Offset.
unsigned computeSizeAndOffset(DIE &Die, unsigned Offset);
- /// \brief Compute the size and offset of all the DIEs.
+ /// Compute the size and offset of all the DIEs.
void computeSizeAndOffsets();
- /// \brief Compute the size and offset of all the DIEs in the given unit.
+ /// Compute the size and offset of all the DIEs in the given unit.
/// \returns The size of the root DIE.
unsigned computeSizeAndOffsetsForUnit(DwarfUnit *TheU);
- /// \brief Add a unit to the list of CUs.
+ /// Add a unit to the list of CUs.
void addUnit(std::unique_ptr<DwarfCompileUnit> U);
- /// \brief Emit all of the units to the section listed with the given
+ /// Emit all of the units to the section listed with the given
/// abbreviation section.
void emitUnits(bool UseOffsets);
- /// \brief Emit the given unit to its section.
+ /// Emit the given unit to its section.
void emitUnit(DwarfUnit *U, bool UseOffsets);
- /// \brief Emit a set of abbreviations to the specific section.
+ /// Emit a set of abbreviations to the specific section.
void emitAbbrevs(MCSection *);
- /// \brief Emit all of the strings to the section given.
- void emitStrings(MCSection *StrSection, MCSection *OffsetSection = nullptr);
+ /// Emit all of the strings to the section given. If OffsetSection is
+ /// non-null, emit a table of string offsets to it. If UseRelativeOffsets
+ /// is false, emit absolute offsets to the strings. Otherwise, emit
+ /// relocatable references to the strings if they are supported by the target.
+ void emitStrings(MCSection *StrSection, MCSection *OffsetSection = nullptr,
+ bool UseRelativeOffsets = false);
- /// \brief Returns the string pool.
+ /// Returns the string pool.
DwarfStringPool &getStringPool() { return StrPool; }
+ MCSymbol *getStringOffsetsStartSym() const { return StringOffsetsStartSym; }
+
+ void setStringOffsetsStartSym(MCSymbol *Sym) { StringOffsetsStartSym = Sym; }
+
+ MCSymbol *getRnglistsTableBaseSym() const { return RnglistsTableBaseSym; }
+
+ void setRnglistsTableBaseSym(MCSymbol *Sym) { RnglistsTableBaseSym = Sym; }
+
/// \returns false if the variable was merged with a previous one.
bool addScopeVariable(LexicalScope *LS, DbgVariable *Var);
- DenseMap<LexicalScope *, SmallVector<DbgVariable *, 8>> &getScopeVariables() {
+ DenseMap<LexicalScope *, ScopeVars> &getScopeVariables() {
return ScopeVariables;
}
diff --git a/lib/CodeGen/AsmPrinter/DwarfStringPool.cpp b/lib/CodeGen/AsmPrinter/DwarfStringPool.cpp
index aa5f01e88933..a61fa83cfb03 100644
--- a/lib/CodeGen/AsmPrinter/DwarfStringPool.cpp
+++ b/lib/CodeGen/AsmPrinter/DwarfStringPool.cpp
@@ -39,8 +39,30 @@ DwarfStringPool::EntryRef DwarfStringPool::getEntry(AsmPrinter &Asm,
return EntryRef(*I.first);
}
+void DwarfStringPool::emitStringOffsetsTableHeader(AsmPrinter &Asm,
+ MCSection *Section,
+ MCSymbol *StartSym) {
+ if (empty())
+ return;
+ Asm.OutStreamer->SwitchSection(Section);
+ unsigned EntrySize = 4;
+ // FIXME: DWARF64
+ // We are emitting the header for a contribution to the string offsets
+ // table. The header consists of an entry with the contribution's
+ // size (not including the size of the length field), the DWARF version and
+ // 2 bytes of padding.
+ Asm.emitInt32(size() * EntrySize + 4);
+ Asm.emitInt16(Asm.getDwarfVersion());
+ Asm.emitInt16(0);
+ // Define the symbol that marks the start of the contribution. It is
+ // referenced by most unit headers via DW_AT_str_offsets_base.
+ // Split units do not use the attribute.
+ if (StartSym)
+ Asm.OutStreamer->EmitLabel(StartSym);
+}
+
void DwarfStringPool::emit(AsmPrinter &Asm, MCSection *StrSection,
- MCSection *OffsetSection) {
+ MCSection *OffsetSection, bool UseRelativeOffsets) {
if (Pool.empty())
return;
@@ -74,6 +96,9 @@ void DwarfStringPool::emit(AsmPrinter &Asm, MCSection *StrSection,
Asm.OutStreamer->SwitchSection(OffsetSection);
unsigned size = 4; // FIXME: DWARF64 is 8.
for (const auto &Entry : Entries)
- Asm.OutStreamer->EmitIntValue(Entry->getValue().Offset, size);
+ if (UseRelativeOffsets)
+ Asm.emitDwarfStringOffset(Entry->getValue());
+ else
+ Asm.OutStreamer->EmitIntValue(Entry->getValue().Offset, size);
}
}
diff --git a/lib/CodeGen/AsmPrinter/DwarfStringPool.h b/lib/CodeGen/AsmPrinter/DwarfStringPool.h
index 1cac3b7c8432..6e6988ea4ad4 100644
--- a/lib/CodeGen/AsmPrinter/DwarfStringPool.h
+++ b/lib/CodeGen/AsmPrinter/DwarfStringPool.h
@@ -19,6 +19,7 @@ namespace llvm {
class AsmPrinter;
class MCSection;
+class MCSymbol;
// Collection of strings for this unit and assorted symbols.
// A String->Symbol mapping of strings used by indirect
@@ -36,11 +37,17 @@ public:
DwarfStringPool(BumpPtrAllocator &A, AsmPrinter &Asm, StringRef Prefix);
+ void emitStringOffsetsTableHeader(AsmPrinter &Asm, MCSection *OffsetSection,
+ MCSymbol *StartSym);
+
void emit(AsmPrinter &Asm, MCSection *StrSection,
- MCSection *OffsetSection = nullptr);
+ MCSection *OffsetSection = nullptr,
+ bool UseRelativeOffsets = false);
bool empty() const { return Pool.empty(); }
+ unsigned size() const { return Pool.size(); }
+
/// Get a reference to an entry in the string pool.
EntryRef getEntry(AsmPrinter &Asm, StringRef Str);
};
diff --git a/lib/CodeGen/AsmPrinter/DwarfUnit.cpp b/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
index 911e46235781..43b835b2c4aa 100644
--- a/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
+++ b/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
@@ -19,10 +19,10 @@
#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/None.h"
+#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineOperand.h"
-#include "llvm/CodeGen/TargetLoweringObjectFile.h"
#include "llvm/CodeGen/TargetRegisterInfo.h"
#include "llvm/CodeGen/TargetSubtargetInfo.h"
#include "llvm/IR/Constants.h"
@@ -30,12 +30,14 @@
#include "llvm/IR/GlobalValue.h"
#include "llvm/IR/Metadata.h"
#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCDwarf.h"
#include "llvm/MC/MCSection.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MachineLocation.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/CommandLine.h"
+#include "llvm/Target/TargetLoweringObjectFile.h"
#include <cassert>
#include <cstdint>
#include <string>
@@ -45,11 +47,6 @@ using namespace llvm;
#define DEBUG_TYPE "dwarfdebug"
-static cl::opt<bool>
-GenerateDwarfTypeUnits("generate-type-units", cl::Hidden,
- cl::desc("Generate DWARF4 type units."),
- cl::init(false));
-
DIEDwarfExpression::DIEDwarfExpression(const AsmPrinter &AP, DwarfUnit &DU,
DIELoc &DIE)
: DwarfExpression(AP.getDwarfVersion()), AP(AP), DU(DU),
@@ -83,8 +80,6 @@ DwarfTypeUnit::DwarfTypeUnit(DwarfCompileUnit &CU, AsmPrinter *A,
MCDwarfDwoLineTable *SplitLineTable)
: DwarfUnit(dwarf::DW_TAG_type_unit, CU.getCUNode(), A, DW, DWU), CU(CU),
SplitLineTable(SplitLineTable) {
- if (SplitLineTable)
- addSectionOffset(getUnitDie(), dwarf::DW_AT_stmt_list, 0);
}
DwarfUnit::~DwarfUnit() {
@@ -185,7 +180,7 @@ bool DwarfUnit::isShareableAcrossCUs(const DINode *D) const {
return false;
return (isa<DIType>(D) ||
(isa<DISubprogram>(D) && !cast<DISubprogram>(D)->isDefinition())) &&
- !GenerateDwarfTypeUnits;
+ !DD->generateTypeUnits();
}
DIE *DwarfUnit::getDIE(const DINode *D) const {
@@ -239,9 +234,28 @@ void DwarfUnit::addSInt(DIELoc &Die, Optional<dwarf::Form> Form,
void DwarfUnit::addString(DIE &Die, dwarf::Attribute Attribute,
StringRef String) {
- Die.addValue(DIEValueAllocator, Attribute,
- isDwoUnit() ? dwarf::DW_FORM_GNU_str_index : dwarf::DW_FORM_strp,
- DIEString(DU->getStringPool().getEntry(*Asm, String)));
+ if (DD->useInlineStrings()) {
+ Die.addValue(DIEValueAllocator, Attribute, dwarf::DW_FORM_string,
+ new (DIEValueAllocator)
+ DIEInlineString(String, DIEValueAllocator));
+ return;
+ }
+ auto StringPoolEntry = DU->getStringPool().getEntry(*Asm, String);
+ dwarf::Form IxForm =
+ isDwoUnit() ? dwarf::DW_FORM_GNU_str_index : dwarf::DW_FORM_strp;
+ // For DWARF v5 and beyond, use the smallest strx? form possible.
+ if (useSegmentedStringOffsetsTable()) {
+ IxForm = dwarf::DW_FORM_strx1;
+ unsigned Index = StringPoolEntry.getIndex();
+ if (Index > 0xffffff)
+ IxForm = dwarf::DW_FORM_strx4;
+ else if (Index > 0xffff)
+ IxForm = dwarf::DW_FORM_strx3;
+ else if (Index > 0xff)
+ IxForm = dwarf::DW_FORM_strx2;
+ }
+ Die.addValue(DIEValueAllocator, Attribute, IxForm,
+ DIEString(StringPoolEntry));
}
DIEValueList::value_iterator DwarfUnit::addLabel(DIEValueList &Die,
@@ -263,9 +277,33 @@ void DwarfUnit::addSectionOffset(DIE &Die, dwarf::Attribute Attribute,
addUInt(Die, Attribute, dwarf::DW_FORM_data4, Integer);
}
-unsigned DwarfTypeUnit::getOrCreateSourceID(StringRef FileName, StringRef DirName) {
- return SplitLineTable ? SplitLineTable->getFile(DirName, FileName)
- : getCU().getOrCreateSourceID(FileName, DirName);
+MD5::MD5Result *DwarfUnit::getMD5AsBytes(const DIFile *File) const {
+ assert(File);
+ if (DD->getDwarfVersion() < 5)
+ return nullptr;
+ Optional<DIFile::ChecksumInfo<StringRef>> Checksum = File->getChecksum();
+ if (!Checksum || Checksum->Kind != DIFile::CSK_MD5)
+ return nullptr;
+
+ // Convert the string checksum to an MD5Result for the streamer.
+ // The verifier validates the checksum so we assume it's okay.
+ // An MD5 checksum is 16 bytes.
+ std::string ChecksumString = fromHex(Checksum->Value);
+ void *CKMem = Asm->OutStreamer->getContext().allocate(16, 1);
+ memcpy(CKMem, ChecksumString.data(), 16);
+ return reinterpret_cast<MD5::MD5Result *>(CKMem);
+}
+
+unsigned DwarfTypeUnit::getOrCreateSourceID(const DIFile *File) {
+ if (!SplitLineTable)
+ return getCU().getOrCreateSourceID(File);
+ if (!UsedLineTable) {
+ UsedLineTable = true;
+ // This is a split type unit that needs a line table.
+ addSectionOffset(getUnitDie(), dwarf::DW_AT_stmt_list, 0);
+ }
+ return SplitLineTable->getFile(File->getDirectory(), File->getFilename(),
+ getMD5AsBytes(File), File->getSource());
}
void DwarfUnit::addOpAddress(DIELoc &Die, const MCSymbol *Sym) {
@@ -335,12 +373,11 @@ void DwarfUnit::addBlock(DIE &Die, dwarf::Attribute Attribute,
Die.addValue(DIEValueAllocator, Attribute, Block->BestForm(), Block);
}
-void DwarfUnit::addSourceLine(DIE &Die, unsigned Line, StringRef File,
- StringRef Directory) {
+void DwarfUnit::addSourceLine(DIE &Die, unsigned Line, const DIFile *File) {
if (Line == 0)
return;
- unsigned FileID = getOrCreateSourceID(File, Directory);
+ unsigned FileID = getOrCreateSourceID(File);
assert(FileID && "Invalid file id");
addUInt(Die, dwarf::DW_AT_decl_file, None, FileID);
addUInt(Die, dwarf::DW_AT_decl_line, None, Line);
@@ -349,32 +386,31 @@ void DwarfUnit::addSourceLine(DIE &Die, unsigned Line, StringRef File,
void DwarfUnit::addSourceLine(DIE &Die, const DILocalVariable *V) {
assert(V);
- addSourceLine(Die, V->getLine(), V->getScope()->getFilename(),
- V->getScope()->getDirectory());
+ addSourceLine(Die, V->getLine(), V->getFile());
}
void DwarfUnit::addSourceLine(DIE &Die, const DIGlobalVariable *G) {
assert(G);
- addSourceLine(Die, G->getLine(), G->getFilename(), G->getDirectory());
+ addSourceLine(Die, G->getLine(), G->getFile());
}
void DwarfUnit::addSourceLine(DIE &Die, const DISubprogram *SP) {
assert(SP);
- addSourceLine(Die, SP->getLine(), SP->getFilename(), SP->getDirectory());
+ addSourceLine(Die, SP->getLine(), SP->getFile());
}
void DwarfUnit::addSourceLine(DIE &Die, const DIType *Ty) {
assert(Ty);
- addSourceLine(Die, Ty->getLine(), Ty->getFilename(), Ty->getDirectory());
+ addSourceLine(Die, Ty->getLine(), Ty->getFile());
}
void DwarfUnit::addSourceLine(DIE &Die, const DIObjCProperty *Ty) {
assert(Ty);
- addSourceLine(Die, Ty->getLine(), Ty->getFilename(), Ty->getDirectory());
+ addSourceLine(Die, Ty->getLine(), Ty->getFile());
}
/* Byref variables, in Blocks, are declared by the programmer as "SomeType
@@ -727,7 +763,7 @@ DIE *DwarfUnit::getOrCreateTypeDIE(const MDNode *TyNode) {
else if (auto *STy = dyn_cast<DISubroutineType>(Ty))
constructTypeDIE(TyDIE, STy);
else if (auto *CTy = dyn_cast<DICompositeType>(Ty)) {
- if (GenerateDwarfTypeUnits && !Ty->isForwardDecl())
+ if (DD->generateTypeUnits() && !Ty->isForwardDecl())
if (MDString *TypeId = CTy->getRawIdentifier()) {
DD->addDwarfTypeUnitType(getCU(), TypeId->getString(), TyDIE, CTy);
// Skip updating the accelerator tables since this is not the full type.
@@ -917,9 +953,24 @@ void DwarfUnit::constructTypeDIE(DIE &Buffer, const DICompositeType *CTy) {
case dwarf::DW_TAG_enumeration_type:
constructEnumTypeDIE(Buffer, CTy);
break;
+ case dwarf::DW_TAG_variant_part:
case dwarf::DW_TAG_structure_type:
case dwarf::DW_TAG_union_type:
case dwarf::DW_TAG_class_type: {
+ // Emit the discriminator for a variant part.
+ DIDerivedType *Discriminator = nullptr;
+ if (Tag == dwarf::DW_TAG_variant_part) {
+ Discriminator = CTy->getDiscriminator();
+ if (Discriminator) {
+ // DWARF says:
+ // If the variant part has a discriminant, the discriminant is
+ // represented by a separate debugging information entry which is
+ // a child of the variant part entry.
+ DIE &DiscMember = constructMemberDIE(Buffer, Discriminator);
+ addDIEEntry(Buffer, dwarf::DW_AT_discr, DiscMember);
+ }
+ }
+
// Add elements to structure type.
DINodeArray Elements = CTy->getElements();
for (const auto *Element : Elements) {
@@ -933,6 +984,18 @@ void DwarfUnit::constructTypeDIE(DIE &Buffer, const DICompositeType *CTy) {
addType(ElemDie, resolve(DDTy->getBaseType()), dwarf::DW_AT_friend);
} else if (DDTy->isStaticMember()) {
getOrCreateStaticMemberDIE(DDTy);
+ } else if (Tag == dwarf::DW_TAG_variant_part) {
+ // When emitting a variant part, wrap each member in
+ // DW_TAG_variant.
+ DIE &Variant = createAndAddDIE(dwarf::DW_TAG_variant, Buffer);
+ if (const ConstantInt *CI =
+ dyn_cast_or_null<ConstantInt>(DDTy->getDiscriminantValue())) {
+ if (isUnsignedDIType(DD, resolve(Discriminator->getBaseType())))
+ addUInt(Variant, dwarf::DW_AT_discr_value, None, CI->getZExtValue());
+ else
+ addSInt(Variant, dwarf::DW_AT_discr_value, None, CI->getSExtValue());
+ }
+ constructMemberDIE(Variant, DDTy);
} else {
constructMemberDIE(Buffer, DDTy);
}
@@ -952,6 +1015,11 @@ void DwarfUnit::constructTypeDIE(DIE &Buffer, const DICompositeType *CTy) {
if (unsigned PropertyAttributes = Property->getAttributes())
addUInt(ElemDie, dwarf::DW_AT_APPLE_property_attribute, None,
PropertyAttributes);
+ } else if (auto *Composite = dyn_cast<DICompositeType>(Element)) {
+ if (Composite->getTag() == dwarf::DW_TAG_variant_part) {
+ DIE &VariantPart = createAndAddDIE(Composite->getTag(), Buffer);
+ constructTypeDIE(VariantPart, Composite);
+ }
}
}
@@ -975,6 +1043,15 @@ void DwarfUnit::constructTypeDIE(DIE &Buffer, const DICompositeType *CTy) {
Tag == dwarf::DW_TAG_structure_type || Tag == dwarf::DW_TAG_union_type)
addTemplateParams(Buffer, CTy->getTemplateParams());
+ // Add the type's non-standard calling convention.
+ uint8_t CC = 0;
+ if (CTy->isTypePassByValue())
+ CC = dwarf::DW_CC_pass_by_value;
+ else if (CTy->isTypePassByReference())
+ CC = dwarf::DW_CC_pass_by_reference;
+ if (CC)
+ addUInt(Buffer, dwarf::DW_AT_calling_convention, dwarf::DW_FORM_data1,
+ CC);
break;
}
default:
@@ -1152,9 +1229,8 @@ bool DwarfUnit::applySubprogramDefinitionAttributes(const DISubprogram *SP,
// Look at the Decl's linkage name only if we emitted it.
if (DD->useAllLinkageNames())
DeclLinkageName = SPDecl->getLinkageName();
- unsigned DeclID =
- getOrCreateSourceID(SPDecl->getFilename(), SPDecl->getDirectory());
- unsigned DefID = getOrCreateSourceID(SP->getFilename(), SP->getDirectory());
+ unsigned DeclID = getOrCreateSourceID(SPDecl->getFile());
+ unsigned DefID = getOrCreateSourceID(SP->getFile());
if (DeclID != DefID)
addUInt(SPDie, dwarf::DW_AT_decl_file, None, DefID);
@@ -1304,14 +1380,17 @@ void DwarfUnit::constructSubrangeDIE(DIE &Buffer, const DISubrange *SR,
// DW_AT_lower_bound and DW_AT_count attributes.
int64_t LowerBound = SR->getLowerBound();
int64_t DefaultLowerBound = getDefaultLowerBound();
- int64_t Count = SR->getCount();
+ int64_t Count = -1;
+ if (auto *CI = SR->getCount().dyn_cast<ConstantInt*>())
+ Count = CI->getSExtValue();
if (DefaultLowerBound == -1 || LowerBound != DefaultLowerBound)
addUInt(DW_Subrange, dwarf::DW_AT_lower_bound, None, LowerBound);
- if (Count != -1)
- // FIXME: An unbounded array should reference the expression that defines
- // the array.
+ if (auto *CV = SR->getCount().dyn_cast<DIVariable*>()) {
+ if (auto *CountVarDIE = getDIE(CV))
+ addDIEEntry(DW_Subrange, dwarf::DW_AT_count, *CountVarDIE);
+ } else if (Count != -1)
addUInt(DW_Subrange, dwarf::DW_AT_count, None, Count);
}
@@ -1320,16 +1399,49 @@ DIE *DwarfUnit::getIndexTyDie() {
return IndexTyDie;
// Construct an integer type to use for indexes.
IndexTyDie = &createAndAddDIE(dwarf::DW_TAG_base_type, getUnitDie());
- addString(*IndexTyDie, dwarf::DW_AT_name, "sizetype");
+ StringRef Name = "__ARRAY_SIZE_TYPE__";
+ addString(*IndexTyDie, dwarf::DW_AT_name, Name);
addUInt(*IndexTyDie, dwarf::DW_AT_byte_size, None, sizeof(int64_t));
addUInt(*IndexTyDie, dwarf::DW_AT_encoding, dwarf::DW_FORM_data1,
dwarf::DW_ATE_unsigned);
+ DD->addAccelType(Name, *IndexTyDie, /*Flags*/ 0);
return IndexTyDie;
}
+/// Returns true if the vector's size differs from the sum of sizes of elements
+/// the user specified. This can occur if the vector has been rounded up to
+/// fit memory alignment constraints.
+static bool hasVectorBeenPadded(const DICompositeType *CTy) {
+ assert(CTy && CTy->isVector() && "Composite type is not a vector");
+ const uint64_t ActualSize = CTy->getSizeInBits();
+
+ // Obtain the size of each element in the vector.
+ DIType *BaseTy = CTy->getBaseType().resolve();
+ assert(BaseTy && "Unknown vector element type.");
+ const uint64_t ElementSize = BaseTy->getSizeInBits();
+
+ // Locate the number of elements in the vector.
+ const DINodeArray Elements = CTy->getElements();
+ assert(Elements.size() == 1 &&
+ Elements[0]->getTag() == dwarf::DW_TAG_subrange_type &&
+ "Invalid vector element array, expected one element of type subrange");
+ const auto Subrange = cast<DISubrange>(Elements[0]);
+ const auto CI = Subrange->getCount().get<ConstantInt *>();
+ const int32_t NumVecElements = CI->getSExtValue();
+
+ // Ensure we found the element count and that the actual size is wide
+ // enough to contain the requested size.
+ assert(ActualSize >= (NumVecElements * ElementSize) && "Invalid vector size");
+ return ActualSize != (NumVecElements * ElementSize);
+}
+
void DwarfUnit::constructArrayTypeDIE(DIE &Buffer, const DICompositeType *CTy) {
- if (CTy->isVector())
+ if (CTy->isVector()) {
addFlag(Buffer, dwarf::DW_AT_GNU_vector);
+ if (hasVectorBeenPadded(CTy))
+ addUInt(Buffer, dwarf::DW_AT_byte_size, None,
+ CTy->getSizeInBits() / CHAR_BIT);
+ }
// Emit the element type.
addType(Buffer, resolve(CTy->getBaseType()));
@@ -1350,6 +1462,15 @@ void DwarfUnit::constructArrayTypeDIE(DIE &Buffer, const DICompositeType *CTy) {
}
void DwarfUnit::constructEnumTypeDIE(DIE &Buffer, const DICompositeType *CTy) {
+ const DIType *DTy = resolve(CTy->getBaseType());
+ bool IsUnsigned = DTy && isUnsignedDIType(DD, DTy);
+ if (DTy) {
+ if (DD->getDwarfVersion() >= 3)
+ addType(Buffer, DTy);
+ if (DD->getDwarfVersion() >= 4 && (CTy->getFlags() & DINode::FlagFixedEnum))
+ addFlag(Buffer, dwarf::DW_AT_enum_class);
+ }
+
DINodeArray Elements = CTy->getElements();
// Add enumerators to enumeration type.
@@ -1359,16 +1480,10 @@ void DwarfUnit::constructEnumTypeDIE(DIE &Buffer, const DICompositeType *CTy) {
DIE &Enumerator = createAndAddDIE(dwarf::DW_TAG_enumerator, Buffer);
StringRef Name = Enum->getName();
addString(Enumerator, dwarf::DW_AT_name, Name);
- int64_t Value = Enum->getValue();
- addSInt(Enumerator, dwarf::DW_AT_const_value, dwarf::DW_FORM_sdata,
- Value);
+ auto Value = static_cast<uint64_t>(Enum->getValue());
+ addConstantValue(Enumerator, IsUnsigned, Value);
}
}
- const DIType *DTy = resolve(CTy->getBaseType());
- if (DTy) {
- addType(Buffer, DTy);
- addFlag(Buffer, dwarf::DW_AT_enum_class);
- }
}
void DwarfUnit::constructContainingTypeDIEs() {
@@ -1385,13 +1500,14 @@ void DwarfUnit::constructContainingTypeDIEs() {
}
}
-void DwarfUnit::constructMemberDIE(DIE &Buffer, const DIDerivedType *DT) {
+DIE &DwarfUnit::constructMemberDIE(DIE &Buffer, const DIDerivedType *DT) {
DIE &MemberDie = createAndAddDIE(DT->getTag(), Buffer);
StringRef Name = DT->getName();
if (!Name.empty())
addString(MemberDie, dwarf::DW_AT_name, Name);
- addType(MemberDie, resolve(DT->getBaseType()));
+ if (DIType *Resolved = resolve(DT->getBaseType()))
+ addType(MemberDie, Resolved);
addSourceLine(MemberDie, DT);
@@ -1489,6 +1605,8 @@ void DwarfUnit::constructMemberDIE(DIE &Buffer, const DIDerivedType *DT) {
if (DT->isArtificial())
addFlag(MemberDie, dwarf::DW_AT_artificial);
+
+ return MemberDie;
}
DIE *DwarfUnit::getOrCreateStaticMemberDIE(const DIDerivedType *DT) {
@@ -1541,18 +1659,18 @@ DIE *DwarfUnit::getOrCreateStaticMemberDIE(const DIDerivedType *DT) {
void DwarfUnit::emitCommonHeader(bool UseOffsets, dwarf::UnitType UT) {
// Emit size of content not including length itself
Asm->OutStreamer->AddComment("Length of Unit");
- Asm->EmitInt32(getHeaderSize() + getUnitDie().getSize());
+ Asm->emitInt32(getHeaderSize() + getUnitDie().getSize());
Asm->OutStreamer->AddComment("DWARF version number");
unsigned Version = DD->getDwarfVersion();
- Asm->EmitInt16(Version);
+ Asm->emitInt16(Version);
// DWARF v5 reorders the address size and adds a unit type.
if (Version >= 5) {
Asm->OutStreamer->AddComment("DWARF Unit Type");
- Asm->EmitInt8(UT);
+ Asm->emitInt8(UT);
Asm->OutStreamer->AddComment("Address Size (in bytes)");
- Asm->EmitInt8(Asm->MAI->getCodePointerSize());
+ Asm->emitInt8(Asm->MAI->getCodePointerSize());
}
// We share one abbreviations table across all units so it's always at the
@@ -1561,14 +1679,14 @@ void DwarfUnit::emitCommonHeader(bool UseOffsets, dwarf::UnitType UT) {
Asm->OutStreamer->AddComment("Offset Into Abbrev. Section");
const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering();
if (UseOffsets)
- Asm->EmitInt32(0);
+ Asm->emitInt32(0);
else
Asm->emitDwarfSymbolReference(
TLOF.getDwarfAbbrevSection()->getBeginSymbol(), false);
if (Version <= 4) {
Asm->OutStreamer->AddComment("Address Size (in bytes)");
- Asm->EmitInt8(Asm->MAI->getCodePointerSize());
+ Asm->emitInt8(Asm->MAI->getCodePointerSize());
}
}
@@ -1627,3 +1745,19 @@ const MCSymbol *DwarfUnit::getCrossSectionRelativeBaseAddress() const {
return nullptr;
return getSection()->getBeginSymbol();
}
+
+void DwarfUnit::addStringOffsetsStart() {
+ const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering();
+ addSectionLabel(getUnitDie(), dwarf::DW_AT_str_offsets_base,
+ DU->getStringOffsetsStartSym(),
+ TLOF.getDwarfStrOffSection()->getBeginSymbol());
+}
+
+void DwarfUnit::addRnglistsBase() {
+ assert(DD->getDwarfVersion() >= 5 &&
+ "DW_AT_rnglists_base requires DWARF version 5 or later");
+ const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering();
+ addSectionLabel(getUnitDie(), dwarf::DW_AT_rnglists_base,
+ DU->getRnglistsTableBaseSym(),
+ TLOF.getDwarfRnglistsSection()->getBeginSymbol());
+}
diff --git a/lib/CodeGen/AsmPrinter/DwarfUnit.h b/lib/CodeGen/AsmPrinter/DwarfUnit.h
index 4cc01b3298d4..69696f626536 100644
--- a/lib/CodeGen/AsmPrinter/DwarfUnit.h
+++ b/lib/CodeGen/AsmPrinter/DwarfUnit.h
@@ -98,7 +98,7 @@ protected:
/// corresponds to the MDNode mapped with the subprogram DIE.
DenseMap<DIE *, const DINode *> ContainingTypeMap;
- DwarfUnit(dwarf::Tag, const DICompileUnit *CU, AsmPrinter *A, DwarfDebug *DW,
+ DwarfUnit(dwarf::Tag, const DICompileUnit *Node, AsmPrinter *A, DwarfDebug *DW,
DwarfFile *DWU);
bool applySubprogramDefinitionAttributes(const DISubprogram *SP, DIE &SPDie);
@@ -112,6 +112,8 @@ public:
uint16_t getLanguage() const { return CUNode->getSourceLanguage(); }
const DICompileUnit *getCUNode() const { return CUNode; }
+ uint16_t getDwarfVersion() const { return DD->getDwarfVersion(); }
+
/// Return true if this compile unit has something to write out.
bool hasContent() const { return getUnitDie().hasChildren(); }
@@ -185,7 +187,7 @@ public:
/// Add a dwarf op address data and value using the form given and an
/// op of either DW_FORM_addr or DW_FORM_GNU_addr_index.
- void addOpAddress(DIELoc &Die, const MCSymbol *Label);
+ void addOpAddress(DIELoc &Die, const MCSymbol *Sym);
/// Add a label delta attribute data and value.
void addLabelDelta(DIE &Die, dwarf::Attribute Attribute, const MCSymbol *Hi,
@@ -201,14 +203,13 @@ public:
void addDIETypeSignature(DIE &Die, uint64_t Signature);
/// Add block data.
- void addBlock(DIE &Die, dwarf::Attribute Attribute, DIELoc *Block);
+ void addBlock(DIE &Die, dwarf::Attribute Attribute, DIELoc *Loc);
/// Add block data.
void addBlock(DIE &Die, dwarf::Attribute Attribute, DIEBlock *Block);
/// Add location information to specified debug information entry.
- void addSourceLine(DIE &Die, unsigned Line, StringRef File,
- StringRef Directory);
+ void addSourceLine(DIE &Die, unsigned Line, const DIFile *File);
void addSourceLine(DIE &Die, const DILocalVariable *V);
void addSourceLine(DIE &Die, const DIGlobalVariable *G);
void addSourceLine(DIE &Die, const DISubprogram *SP);
@@ -259,7 +260,7 @@ public:
bool SkipSPAttributes = false);
/// Find existing DIE or create new DIE for the given type.
- DIE *getOrCreateTypeDIE(const MDNode *N);
+ DIE *getOrCreateTypeDIE(const MDNode *TyNode);
/// Get context owner's DIE.
DIE *getOrCreateContextDIE(const DIScope *Context);
@@ -274,6 +275,10 @@ public:
/// call insertDIE if MD is not null.
DIE &createAndAddDIE(unsigned Tag, DIE &Parent, const DINode *N = nullptr);
+ bool useSegmentedStringOffsetsTable() const {
+ return DD->useSegmentedStringOffsetsTable();
+ }
+
/// Compute the size of a header for this unit, not including the initial
/// length field.
virtual unsigned getHeaderSize() const {
@@ -287,6 +292,12 @@ public:
/// Emit the header for this unit, not including the initial length field.
virtual void emitHeader(bool UseOffsets) = 0;
+ /// Add the DW_AT_str_offsets_base attribute to the unit DIE.
+ void addStringOffsetsStart();
+
+ /// Add the DW_AT_rnglists_base attribute to the unit DIE.
+ void addRnglistsBase();
+
virtual DwarfCompileUnit &getCU() = 0;
void constructTypeDIE(DIE &Buffer, const DICompositeType *CTy);
@@ -300,15 +311,19 @@ public:
const MCSymbol *Label,
const MCSymbol *Sec);
+ /// If the \p File has an MD5 checksum, return it as an MD5Result
+ /// allocated in the MCContext.
+ MD5::MD5Result *getMD5AsBytes(const DIFile *File) const;
+
protected:
~DwarfUnit();
/// Create new static data member DIE.
DIE *getOrCreateStaticMemberDIE(const DIDerivedType *DT);
- /// Look up the source ID with the given directory and source file names. If
- /// none currently exists, create a new ID and insert it in the line table.
- virtual unsigned getOrCreateSourceID(StringRef File, StringRef Directory) = 0;
+ /// Look up the source ID for the given file. If none currently exists,
+ /// create a new ID and insert it in the line table.
+ virtual unsigned getOrCreateSourceID(const DIFile *File) = 0;
/// Look in the DwarfDebug map for the MDNode that corresponds to the
/// reference.
@@ -327,11 +342,11 @@ protected:
private:
void constructTypeDIE(DIE &Buffer, const DIBasicType *BTy);
void constructTypeDIE(DIE &Buffer, const DIDerivedType *DTy);
- void constructTypeDIE(DIE &Buffer, const DISubroutineType *DTy);
+ void constructTypeDIE(DIE &Buffer, const DISubroutineType *CTy);
void constructSubrangeDIE(DIE &Buffer, const DISubrange *SR, DIE *IndexTy);
void constructArrayTypeDIE(DIE &Buffer, const DICompositeType *CTy);
void constructEnumTypeDIE(DIE &Buffer, const DICompositeType *CTy);
- void constructMemberDIE(DIE &Buffer, const DIDerivedType *DT);
+ DIE &constructMemberDIE(DIE &Buffer, const DIDerivedType *DT);
void constructTemplateTypeParameterDIE(DIE &Buffer,
const DITemplateTypeParameter *TP);
void constructTemplateValueParameterDIE(DIE &Buffer,
@@ -357,8 +372,9 @@ class DwarfTypeUnit final : public DwarfUnit {
const DIE *Ty;
DwarfCompileUnit &CU;
MCDwarfDwoLineTable *SplitLineTable;
+ bool UsedLineTable = false;
- unsigned getOrCreateSourceID(StringRef File, StringRef Directory) override;
+ unsigned getOrCreateSourceID(const DIFile *File) override;
bool isDwoUnit() const override;
public:
diff --git a/lib/CodeGen/AsmPrinter/EHStreamer.cpp b/lib/CodeGen/AsmPrinter/EHStreamer.cpp
index 3cdab57bca70..65de9d7e65a4 100644
--- a/lib/CodeGen/AsmPrinter/EHStreamer.cpp
+++ b/lib/CodeGen/AsmPrinter/EHStreamer.cpp
@@ -20,7 +20,6 @@
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineOperand.h"
-#include "llvm/CodeGen/TargetLoweringObjectFile.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/Function.h"
#include "llvm/MC/MCAsmInfo.h"
@@ -30,6 +29,7 @@
#include "llvm/MC/MCTargetOptions.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/LEB128.h"
+#include "llvm/Target/TargetLoweringObjectFile.h"
#include <algorithm>
#include <cassert>
#include <cstdint>
@@ -58,10 +58,10 @@ unsigned EHStreamer::sharedTypeIDs(const LandingPadInfo *L,
/// Compute the actions table and gather the first action index for each landing
/// pad site.
-unsigned EHStreamer::
-computeActionsTable(const SmallVectorImpl<const LandingPadInfo*> &LandingPads,
- SmallVectorImpl<ActionEntry> &Actions,
- SmallVectorImpl<unsigned> &FirstActions) {
+void EHStreamer::computeActionsTable(
+ const SmallVectorImpl<const LandingPadInfo *> &LandingPads,
+ SmallVectorImpl<ActionEntry> &Actions,
+ SmallVectorImpl<unsigned> &FirstActions) {
// The action table follows the call-site table in the LSDA. The individual
// records are of two types:
//
@@ -149,7 +149,7 @@ computeActionsTable(const SmallVectorImpl<const LandingPadInfo*> &LandingPads,
FirstAction = SizeActions + SizeSiteActions - SizeAction + 1;
} // else identical - re-use previous FirstAction
- // Information used when created the call-site table. The action record
+ // Information used when creating the call-site table. The action record
// field of the call site record is the offset of the first associated
// action record, relative to the start of the actions table. This value is
// biased by 1 (1 indicating the start of the actions table), and 0
@@ -161,8 +161,6 @@ computeActionsTable(const SmallVectorImpl<const LandingPadInfo*> &LandingPads,
PrevLPI = LPI;
}
-
- return SizeActions;
}
/// Return `true' if this is a call to a function marked `nounwind'. Return
@@ -361,55 +359,33 @@ void EHStreamer::emitExceptionTable() {
LandingPads.push_back(&PadInfos[i]);
// Order landing pads lexicographically by type id.
- std::sort(LandingPads.begin(), LandingPads.end(),
- [](const LandingPadInfo *L,
- const LandingPadInfo *R) { return L->TypeIds < R->TypeIds; });
+ llvm::sort(LandingPads.begin(), LandingPads.end(),
+ [](const LandingPadInfo *L,
+ const LandingPadInfo *R) { return L->TypeIds < R->TypeIds; });
// Compute the actions table and gather the first action index for each
// landing pad site.
SmallVector<ActionEntry, 32> Actions;
SmallVector<unsigned, 64> FirstActions;
- unsigned SizeActions =
- computeActionsTable(LandingPads, Actions, FirstActions);
+ computeActionsTable(LandingPads, Actions, FirstActions);
// Compute the call-site table.
SmallVector<CallSiteEntry, 64> CallSites;
computeCallSiteTable(CallSites, LandingPads, FirstActions);
- // Final tallies.
-
- // Call sites.
bool IsSJLJ = Asm->MAI->getExceptionHandlingType() == ExceptionHandling::SjLj;
- bool HaveTTData = IsSJLJ ? (!TypeInfos.empty() || !FilterIds.empty()) : true;
-
- unsigned CallSiteTableLength;
- if (IsSJLJ)
- CallSiteTableLength = 0;
- else {
- unsigned SiteStartSize = 4; // dwarf::DW_EH_PE_udata4
- unsigned SiteLengthSize = 4; // dwarf::DW_EH_PE_udata4
- unsigned LandingPadSize = 4; // dwarf::DW_EH_PE_udata4
- CallSiteTableLength =
- CallSites.size() * (SiteStartSize + SiteLengthSize + LandingPadSize);
- }
-
- for (unsigned i = 0, e = CallSites.size(); i < e; ++i) {
- CallSiteTableLength += getULEB128Size(CallSites[i].Action);
- if (IsSJLJ)
- CallSiteTableLength += getULEB128Size(i);
- }
+ unsigned CallSiteEncoding =
+ IsSJLJ ? dwarf::DW_EH_PE_udata4 : dwarf::DW_EH_PE_uleb128;
+ bool HaveTTData = !TypeInfos.empty() || !FilterIds.empty();
// Type infos.
MCSection *LSDASection = Asm->getObjFileLowering().getLSDASection();
unsigned TTypeEncoding;
- unsigned TypeFormatSize;
if (!HaveTTData) {
- // For SjLj exceptions, if there is no TypeInfo, then we just explicitly say
- // that we're omitting that bit.
+ // If there is no TypeInfo, then we just explicitly say that we're omitting
+ // that bit.
TTypeEncoding = dwarf::DW_EH_PE_omit;
- // dwarf::DW_EH_PE_absptr
- TypeFormatSize = Asm->getDataLayout().getPointerSize();
} else {
// Okay, we have actual filters or typeinfos to emit. As such, we need to
// pick a type encoding for them. We're about to emit a list of pointers to
@@ -439,7 +415,6 @@ void EHStreamer::emitExceptionTable() {
// in target-independent code.
//
TTypeEncoding = Asm->getObjFileLowering().getTTypeEncoding();
- TypeFormatSize = Asm->GetSizeOfEncodedValue(TTypeEncoding);
}
// Begin the exception table.
@@ -460,64 +435,35 @@ void EHStreamer::emitExceptionTable() {
Asm->EmitEncodingByte(dwarf::DW_EH_PE_omit, "@LPStart");
Asm->EmitEncodingByte(TTypeEncoding, "@TType");
- // The type infos need to be aligned. GCC does this by inserting padding just
- // before the type infos. However, this changes the size of the exception
- // table, so you need to take this into account when you output the exception
- // table size. However, the size is output using a variable length encoding.
- // So by increasing the size by inserting padding, you may increase the number
- // of bytes used for writing the size. If it increases, say by one byte, then
- // you now need to output one less byte of padding to get the type infos
- // aligned. However this decreases the size of the exception table. This
- // changes the value you have to output for the exception table size. Due to
- // the variable length encoding, the number of bytes used for writing the
- // length may decrease. If so, you then have to increase the amount of
- // padding. And so on. If you look carefully at the GCC code you will see that
- // it indeed does this in a loop, going on and on until the values stabilize.
- // We chose another solution: don't output padding inside the table like GCC
- // does, instead output it before the table.
- unsigned SizeTypes = TypeInfos.size() * TypeFormatSize;
- unsigned CallSiteTableLengthSize = getULEB128Size(CallSiteTableLength);
- unsigned TTypeBaseOffset =
- sizeof(int8_t) + // Call site format
- CallSiteTableLengthSize + // Call site table length size
- CallSiteTableLength + // Call site table length
- SizeActions + // Actions size
- SizeTypes;
- unsigned TTypeBaseOffsetSize = getULEB128Size(TTypeBaseOffset);
- unsigned TotalSize =
- sizeof(int8_t) + // LPStart format
- sizeof(int8_t) + // TType format
- (HaveTTData ? TTypeBaseOffsetSize : 0) + // TType base offset size
- TTypeBaseOffset; // TType base offset
- unsigned PadBytes = (4 - TotalSize) & 3;
-
+ MCSymbol *TTBaseLabel = nullptr;
if (HaveTTData) {
- // Account for any extra padding that will be added to the call site table
- // length.
- Asm->EmitPaddedULEB128(TTypeBaseOffset, TTypeBaseOffsetSize + PadBytes,
- "@TType base offset");
- PadBytes = 0;
+ // N.B.: There is a dependency loop between the size of the TTBase uleb128
+ // here and the amount of padding before the aligned type table. The
+ // assembler must sometimes pad this uleb128 or insert extra padding before
+ // the type table. See PR35809 or GNU as bug 4029.
+ MCSymbol *TTBaseRefLabel = Asm->createTempSymbol("ttbaseref");
+ TTBaseLabel = Asm->createTempSymbol("ttbase");
+ Asm->EmitLabelDifferenceAsULEB128(TTBaseLabel, TTBaseRefLabel);
+ Asm->OutStreamer->EmitLabel(TTBaseRefLabel);
}
bool VerboseAsm = Asm->OutStreamer->isVerboseAsm();
+ // Emit the landing pad call site table.
+ MCSymbol *CstBeginLabel = Asm->createTempSymbol("cst_begin");
+ MCSymbol *CstEndLabel = Asm->createTempSymbol("cst_end");
+ Asm->EmitEncodingByte(CallSiteEncoding, "Call site");
+ Asm->EmitLabelDifferenceAsULEB128(CstEndLabel, CstBeginLabel);
+ Asm->OutStreamer->EmitLabel(CstBeginLabel);
+
// SjLj Exception handling
if (IsSJLJ) {
- Asm->EmitEncodingByte(dwarf::DW_EH_PE_udata4, "Call site");
-
- // Add extra padding if it wasn't added to the TType base offset.
- Asm->EmitPaddedULEB128(CallSiteTableLength,
- CallSiteTableLengthSize + PadBytes,
- "Call site table length");
-
- // Emit the landing pad site information.
unsigned idx = 0;
for (SmallVectorImpl<CallSiteEntry>::const_iterator
I = CallSites.begin(), E = CallSites.end(); I != E; ++I, ++idx) {
const CallSiteEntry &S = *I;
- // Offset of the landing pad, counted in 16-byte bundles relative to the
- // @LPStart address.
+ // Index of the call site entry.
if (VerboseAsm) {
Asm->OutStreamer->AddComment(">> Call Site " + Twine(idx) + " <<");
Asm->OutStreamer->AddComment(" On exception at call site "+Twine(idx));
@@ -557,14 +503,6 @@ void EHStreamer::emitExceptionTable() {
// A missing entry in the call-site table indicates that a call is not
// supposed to throw.
- // Emit the landing pad call site table.
- Asm->EmitEncodingByte(dwarf::DW_EH_PE_udata4, "Call site");
-
- // Add extra padding if it wasn't added to the TType base offset.
- Asm->EmitPaddedULEB128(CallSiteTableLength,
- CallSiteTableLengthSize + PadBytes,
- "Call site table length");
-
unsigned Entry = 0;
for (SmallVectorImpl<CallSiteEntry>::const_iterator
I = CallSites.begin(), E = CallSites.end(); I != E; ++I) {
@@ -579,29 +517,27 @@ void EHStreamer::emitExceptionTable() {
if (!EndLabel)
EndLabel = Asm->getFunctionEnd();
- // Offset of the call site relative to the previous call site, counted in
- // number of 16-byte bundles. The first call site is counted relative to
- // the start of the procedure fragment.
+ // Offset of the call site relative to the start of the procedure.
if (VerboseAsm)
Asm->OutStreamer->AddComment(">> Call Site " + Twine(++Entry) + " <<");
- Asm->EmitLabelDifference(BeginLabel, EHFuncBeginSym, 4);
+ Asm->EmitLabelDifferenceAsULEB128(BeginLabel, EHFuncBeginSym);
if (VerboseAsm)
Asm->OutStreamer->AddComment(Twine(" Call between ") +
BeginLabel->getName() + " and " +
EndLabel->getName());
- Asm->EmitLabelDifference(EndLabel, BeginLabel, 4);
+ Asm->EmitLabelDifferenceAsULEB128(EndLabel, BeginLabel);
- // Offset of the landing pad, counted in 16-byte bundles relative to the
- // @LPStart address.
+ // Offset of the landing pad relative to the start of the procedure.
if (!S.LPad) {
if (VerboseAsm)
Asm->OutStreamer->AddComment(" has no landing pad");
- Asm->OutStreamer->EmitIntValue(0, 4/*size*/);
+ Asm->EmitULEB128(0);
} else {
if (VerboseAsm)
Asm->OutStreamer->AddComment(Twine(" jumps to ") +
S.LPad->LandingPadLabel->getName());
- Asm->EmitLabelDifference(S.LPad->LandingPadLabel, EHFuncBeginSym, 4);
+ Asm->EmitLabelDifferenceAsULEB128(S.LPad->LandingPadLabel,
+ EHFuncBeginSym);
}
// Offset of the first associated action record, relative to the start of
@@ -617,6 +553,7 @@ void EHStreamer::emitExceptionTable() {
Asm->EmitULEB128(S.Action);
}
}
+ Asm->OutStreamer->EmitLabel(CstEndLabel);
// Emit the Action Table.
int Entry = 0;
@@ -660,12 +597,15 @@ void EHStreamer::emitExceptionTable() {
Asm->EmitSLEB128(Action.NextAction);
}
- emitTypeInfos(TTypeEncoding);
+ if (HaveTTData) {
+ Asm->EmitAlignment(2);
+ emitTypeInfos(TTypeEncoding, TTBaseLabel);
+ }
Asm->EmitAlignment(2);
}
-void EHStreamer::emitTypeInfos(unsigned TTypeEncoding) {
+void EHStreamer::emitTypeInfos(unsigned TTypeEncoding, MCSymbol *TTBaseLabel) {
const MachineFunction *MF = Asm->MF;
const std::vector<const GlobalValue *> &TypeInfos = MF->getTypeInfos();
const std::vector<unsigned> &FilterIds = MF->getFilterIds();
@@ -687,6 +627,8 @@ void EHStreamer::emitTypeInfos(unsigned TTypeEncoding) {
Asm->EmitTTypeReference(GV, TTypeEncoding);
}
+ Asm->OutStreamer->EmitLabel(TTBaseLabel);
+
// Emit the Exception Specifications.
if (VerboseAsm && !FilterIds.empty()) {
Asm->OutStreamer->AddComment(">> Filter TypeInfos <<");
diff --git a/lib/CodeGen/AsmPrinter/EHStreamer.h b/lib/CodeGen/AsmPrinter/EHStreamer.h
index 7962b761d8de..b89421a1e067 100644
--- a/lib/CodeGen/AsmPrinter/EHStreamer.h
+++ b/lib/CodeGen/AsmPrinter/EHStreamer.h
@@ -72,9 +72,9 @@ protected:
/// Compute the actions table and gather the first action index for each
/// landing pad site.
- unsigned computeActionsTable(const SmallVectorImpl<const LandingPadInfo*>&LPs,
- SmallVectorImpl<ActionEntry> &Actions,
- SmallVectorImpl<unsigned> &FirstActions);
+ void computeActionsTable(const SmallVectorImpl<const LandingPadInfo *> &LandingPads,
+ SmallVectorImpl<ActionEntry> &Actions,
+ SmallVectorImpl<unsigned> &FirstActions);
void computePadMap(const SmallVectorImpl<const LandingPadInfo *> &LandingPads,
RangeMapType &PadMap);
@@ -86,7 +86,7 @@ protected:
/// no entry and must not be contained in the try-range of any entry - they
/// form gaps in the table. Entries must be ordered by try-range address.
void computeCallSiteTable(SmallVectorImpl<CallSiteEntry> &CallSites,
- const SmallVectorImpl<const LandingPadInfo *> &LPs,
+ const SmallVectorImpl<const LandingPadInfo *> &LandingPads,
const SmallVectorImpl<unsigned> &FirstActions);
/// Emit landing pads and actions.
@@ -110,9 +110,9 @@ protected:
/// catches in the function. This tables is reversed indexed base 1.
void emitExceptionTable();
- virtual void emitTypeInfos(unsigned TTypeEncoding);
+ virtual void emitTypeInfos(unsigned TTypeEncoding, MCSymbol *TTBaseLabel);
- // Helpers for for identifying what kind of clause an EH typeid or selector
+ // Helpers for identifying what kind of clause an EH typeid or selector
// corresponds to. Negative selectors are for filter clauses, the zero
// selector is for cleanups, and positive selectors are for catch clauses.
static bool isFilterEHSelector(int Selector) { return Selector < 0; }
diff --git a/lib/CodeGen/AsmPrinter/ErlangGCPrinter.cpp b/lib/CodeGen/AsmPrinter/ErlangGCPrinter.cpp
index e459c02c9a6e..49cc376fcc98 100644
--- a/lib/CodeGen/AsmPrinter/ErlangGCPrinter.cpp
+++ b/lib/CodeGen/AsmPrinter/ErlangGCPrinter.cpp
@@ -19,7 +19,6 @@
#include "llvm/CodeGen/GCMetadataPrinter.h"
#include "llvm/CodeGen/GCStrategy.h"
#include "llvm/CodeGen/GCs.h"
-#include "llvm/CodeGen/TargetLoweringObjectFile.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Module.h"
@@ -27,6 +26,7 @@
#include "llvm/MC/MCSectionELF.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSymbol.h"
+#include "llvm/Target/TargetLoweringObjectFile.h"
using namespace llvm;
@@ -77,7 +77,7 @@ void ErlangGCPrinter::finishAssembly(Module &M, GCModuleInfo &Info,
// Emit PointCount.
OS.AddComment("safe point count");
- AP.EmitInt16(MD.size());
+ AP.emitInt16(MD.size());
// And each safe point...
for (GCFunctionInfo::iterator PI = MD.begin(), PE = MD.end(); PI != PE;
@@ -94,7 +94,7 @@ void ErlangGCPrinter::finishAssembly(Module &M, GCModuleInfo &Info,
// Emit the stack frame size.
OS.AddComment("stack frame size (in words)");
- AP.EmitInt16(MD.getFrameSize() / IntPtrSize);
+ AP.emitInt16(MD.getFrameSize() / IntPtrSize);
// Emit stack arity, i.e. the number of stacked arguments.
unsigned RegisteredArgs = IntPtrSize == 4 ? 5 : 6;
@@ -102,11 +102,11 @@ void ErlangGCPrinter::finishAssembly(Module &M, GCModuleInfo &Info,
? MD.getFunction().arg_size() - RegisteredArgs
: 0;
OS.AddComment("stack arity");
- AP.EmitInt16(StackArity);
+ AP.emitInt16(StackArity);
// Emit the number of live roots in the function.
OS.AddComment("live root count");
- AP.EmitInt16(MD.live_size(PI));
+ AP.emitInt16(MD.live_size(PI));
// And for each live root...
for (GCFunctionInfo::live_iterator LI = MD.live_begin(PI),
@@ -114,7 +114,7 @@ void ErlangGCPrinter::finishAssembly(Module &M, GCModuleInfo &Info,
LI != LE; ++LI) {
// Emit live root's offset within the stack frame.
OS.AddComment("stack index (offset / wordsize)");
- AP.EmitInt16(LI->StackOffset / IntPtrSize);
+ AP.emitInt16(LI->StackOffset / IntPtrSize);
}
}
}
diff --git a/lib/CodeGen/AsmPrinter/OcamlGCPrinter.cpp b/lib/CodeGen/AsmPrinter/OcamlGCPrinter.cpp
index e0cc241dd23f..59a57ed30d10 100644
--- a/lib/CodeGen/AsmPrinter/OcamlGCPrinter.cpp
+++ b/lib/CodeGen/AsmPrinter/OcamlGCPrinter.cpp
@@ -18,7 +18,6 @@
#include "llvm/CodeGen/GCMetadata.h"
#include "llvm/CodeGen/GCMetadataPrinter.h"
#include "llvm/CodeGen/GCs.h"
-#include "llvm/CodeGen/TargetLoweringObjectFile.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Mangler.h"
@@ -27,6 +26,7 @@
#include "llvm/MC/MCDirectives.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Target/TargetLoweringObjectFile.h"
#include <cctype>
#include <cstddef>
#include <cstdint>
@@ -129,7 +129,7 @@ void OcamlGCMetadataPrinter::finishAssembly(Module &M, GCModuleInfo &Info,
// Very rude!
report_fatal_error(" Too much descriptor for ocaml GC");
}
- AP.EmitInt16(NumDescriptors);
+ AP.emitInt16(NumDescriptors);
AP.EmitAlignment(IntPtrSize == 4 ? 2 : 3);
for (GCModuleInfo::FuncInfoVec::iterator I = Info.funcinfo_begin(),
@@ -166,8 +166,8 @@ void OcamlGCMetadataPrinter::finishAssembly(Module &M, GCModuleInfo &Info,
}
AP.OutStreamer->EmitSymbolValue(J->Label, IntPtrSize);
- AP.EmitInt16(FrameSize);
- AP.EmitInt16(LiveCount);
+ AP.emitInt16(FrameSize);
+ AP.emitInt16(LiveCount);
for (GCFunctionInfo::live_iterator K = FI.live_begin(J),
KE = FI.live_end(J);
@@ -178,7 +178,7 @@ void OcamlGCMetadataPrinter::finishAssembly(Module &M, GCModuleInfo &Info,
"GC root stack offset is outside of fixed stack frame and out "
"of range for ocaml GC!");
}
- AP.EmitInt16(K->StackOffset);
+ AP.emitInt16(K->StackOffset);
}
AP.EmitAlignment(IntPtrSize == 4 ? 2 : 3);
diff --git a/lib/CodeGen/AsmPrinter/WinCFGuard.cpp b/lib/CodeGen/AsmPrinter/WinCFGuard.cpp
new file mode 100644
index 000000000000..18d37caf57ee
--- /dev/null
+++ b/lib/CodeGen/AsmPrinter/WinCFGuard.cpp
@@ -0,0 +1,45 @@
+//===-- CodeGen/AsmPrinter/WinCFGuard.cpp - Control Flow Guard Impl ------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains support for writing Win64 exception info into asm files.
+//
+//===----------------------------------------------------------------------===//
+
+#include "WinCFGuard.h"
+#include "llvm/CodeGen/AsmPrinter.h"
+#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/MachineModuleInfo.h"
+#include "llvm/CodeGen/MachineOperand.h"
+#include "llvm/IR/Constants.h"
+#include "llvm/IR/Metadata.h"
+#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/MC/MCObjectFileInfo.h"
+#include "llvm/MC/MCStreamer.h"
+
+#include <vector>
+
+using namespace llvm;
+
+WinCFGuard::WinCFGuard(AsmPrinter *A) : AsmPrinterHandler(), Asm(A) {}
+
+WinCFGuard::~WinCFGuard() {}
+
+void WinCFGuard::endModule() {
+ const Module *M = Asm->MMI->getModule();
+ std::vector<const Function *> Functions;
+ for (const Function &F : *M)
+ if (F.hasAddressTaken())
+ Functions.push_back(&F);
+ if (Functions.empty())
+ return;
+ auto &OS = *Asm->OutStreamer;
+ OS.SwitchSection(Asm->OutContext.getObjectFileInfo()->getGFIDsSection());
+ for (const Function *F : Functions)
+ OS.EmitCOFFSymbolIndex(Asm->getSymbol(F));
+}
diff --git a/lib/CodeGen/AsmPrinter/WinCFGuard.h b/lib/CodeGen/AsmPrinter/WinCFGuard.h
new file mode 100644
index 000000000000..124e8f04bfad
--- /dev/null
+++ b/lib/CodeGen/AsmPrinter/WinCFGuard.h
@@ -0,0 +1,54 @@
+//===-- WinCFGuard.h - Windows Control Flow Guard Handling ----*- C++ -*--===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains support for writing windows exception info into asm files.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_CODEGEN_ASMPRINTER_WINCFGUARD_H
+#define LLVM_LIB_CODEGEN_ASMPRINTER_WINCFGUARD_H
+
+#include "AsmPrinterHandler.h"
+#include "llvm/Support/Compiler.h"
+
+namespace llvm {
+
+class LLVM_LIBRARY_VISIBILITY WinCFGuard : public AsmPrinterHandler {
+ /// Target of directive emission.
+ AsmPrinter *Asm;
+
+public:
+ WinCFGuard(AsmPrinter *A);
+ ~WinCFGuard() override;
+
+ void setSymbolSize(const MCSymbol *Sym, uint64_t Size) override {}
+
+ /// Emit the Control Flow Guard function ID table
+ void endModule() override;
+
+ /// Gather pre-function debug information.
+ /// Every beginFunction(MF) call should be followed by an endFunction(MF)
+ /// call.
+ void beginFunction(const MachineFunction *MF) override {}
+
+ /// Gather post-function debug information.
+ /// Please note that some AsmPrinter implementations may not call
+ /// beginFunction at all.
+ void endFunction(const MachineFunction *MF) override {}
+
+ /// Process beginning of an instruction.
+ void beginInstruction(const MachineInstr *MI) override {}
+
+ /// Process end of an instruction.
+ void endInstruction() override {}
+};
+
+} // namespace llvm
+
+#endif
diff --git a/lib/CodeGen/AsmPrinter/WinException.cpp b/lib/CodeGen/AsmPrinter/WinException.cpp
index a6a8e84a949f..eff73a58d8d2 100644
--- a/lib/CodeGen/AsmPrinter/WinException.cpp
+++ b/lib/CodeGen/AsmPrinter/WinException.cpp
@@ -21,7 +21,6 @@
#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/CodeGen/TargetFrameLowering.h"
#include "llvm/CodeGen/TargetLowering.h"
-#include "llvm/CodeGen/TargetLoweringObjectFile.h"
#include "llvm/CodeGen/TargetSubtargetInfo.h"
#include "llvm/CodeGen/WinEHFuncInfo.h"
#include "llvm/IR/DataLayout.h"
@@ -35,6 +34,7 @@
#include "llvm/MC/MCSymbol.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FormattedStream.h"
+#include "llvm/Target/TargetLoweringObjectFile.h"
#include "llvm/Target/TargetOptions.h"
using namespace llvm;
diff --git a/lib/CodeGen/AsmPrinter/WinException.h b/lib/CodeGen/AsmPrinter/WinException.h
index 371061c2c2ec..eed3c4453ffc 100644
--- a/lib/CodeGen/AsmPrinter/WinException.h
+++ b/lib/CodeGen/AsmPrinter/WinException.h
@@ -100,7 +100,7 @@ public:
/// Gather and emit post-function exception information.
void endFunction(const MachineFunction *) override;
- /// \brief Emit target-specific EH funclet machinery.
+ /// Emit target-specific EH funclet machinery.
void beginFunclet(const MachineBasicBlock &MBB, MCSymbol *Sym) override;
void endFunclet() override;
};