summaryrefslogtreecommitdiff
path: root/lib/CodeGen/AsmPrinter
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2019-08-20 20:50:12 +0000
committerDimitry Andric <dim@FreeBSD.org>2019-08-20 20:50:12 +0000
commite6d1592492a3a379186bfb02bd0f4eda0669c0d5 (patch)
tree599ab169a01f1c86eda9adc774edaedde2f2db5b /lib/CodeGen/AsmPrinter
parent1a56a5ead7a2e84bee8240f5f6b033b5f1707154 (diff)
Notes
Diffstat (limited to 'lib/CodeGen/AsmPrinter')
-rw-r--r--lib/CodeGen/AsmPrinter/ARMException.cpp7
-rw-r--r--lib/CodeGen/AsmPrinter/AccelTable.cpp46
-rw-r--r--lib/CodeGen/AsmPrinter/AddressPool.cpp31
-rw-r--r--lib/CodeGen/AsmPrinter/AddressPool.h9
-rw-r--r--lib/CodeGen/AsmPrinter/AsmPrinter.cpp279
-rw-r--r--lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp31
-rw-r--r--lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp104
-rw-r--r--lib/CodeGen/AsmPrinter/ByteStreamer.h17
-rw-r--r--lib/CodeGen/AsmPrinter/CodeViewDebug.cpp371
-rw-r--r--lib/CodeGen/AsmPrinter/CodeViewDebug.h24
-rw-r--r--lib/CodeGen/AsmPrinter/DIE.cpp26
-rw-r--r--lib/CodeGen/AsmPrinter/DIEHash.cpp10
-rw-r--r--lib/CodeGen/AsmPrinter/DIEHash.h7
-rw-r--r--lib/CodeGen/AsmPrinter/DbgEntityHistoryCalculator.cpp354
-rw-r--r--lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp74
-rw-r--r--lib/CodeGen/AsmPrinter/DebugLocEntry.h205
-rw-r--r--lib/CodeGen/AsmPrinter/DebugLocStream.cpp7
-rw-r--r--lib/CodeGen/AsmPrinter/DebugLocStream.h7
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfCFIException.cpp7
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp184
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfCompileUnit.h29
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfDebug.cpp668
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfDebug.h92
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfException.h7
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfExpression.cpp120
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfExpression.h86
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfFile.cpp17
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfFile.h10
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfStringPool.cpp7
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfStringPool.h7
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfUnit.cpp197
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfUnit.h38
-rw-r--r--lib/CodeGen/AsmPrinter/EHStreamer.cpp20
-rw-r--r--lib/CodeGen/AsmPrinter/EHStreamer.h7
-rw-r--r--lib/CodeGen/AsmPrinter/ErlangGCPrinter.cpp7
-rw-r--r--lib/CodeGen/AsmPrinter/OcamlGCPrinter.cpp7
-rw-r--r--lib/CodeGen/AsmPrinter/WasmException.cpp11
-rw-r--r--lib/CodeGen/AsmPrinter/WasmException.h7
-rw-r--r--lib/CodeGen/AsmPrinter/WinCFGuard.cpp7
-rw-r--r--lib/CodeGen/AsmPrinter/WinCFGuard.h7
-rw-r--r--lib/CodeGen/AsmPrinter/WinException.cpp49
-rw-r--r--lib/CodeGen/AsmPrinter/WinException.h10
42 files changed, 1984 insertions, 1226 deletions
diff --git a/lib/CodeGen/AsmPrinter/ARMException.cpp b/lib/CodeGen/AsmPrinter/ARMException.cpp
index 9011f025f595..f6ef85a5b78f 100644
--- a/lib/CodeGen/AsmPrinter/ARMException.cpp
+++ b/lib/CodeGen/AsmPrinter/ARMException.cpp
@@ -1,9 +1,8 @@
//===-- CodeGen/AsmPrinter/ARMException.cpp - ARM EHABI Exception Impl ----===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
diff --git a/lib/CodeGen/AsmPrinter/AccelTable.cpp b/lib/CodeGen/AsmPrinter/AccelTable.cpp
index 95875ccb8a0b..b1b7921ea976 100644
--- a/lib/CodeGen/AsmPrinter/AccelTable.cpp
+++ b/lib/CodeGen/AsmPrinter/AccelTable.cpp
@@ -1,9 +1,8 @@
//===- 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.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -56,10 +55,10 @@ 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;
- });
+ llvm::stable_sort(E.second.Values,
+ [](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());
@@ -82,10 +81,9 @@ void AccelTableBase::finalize(AsmPrinter *Asm, StringRef 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;
- });
+ llvm::stable_sort(Bucket, [](HashData *LHS, HashData *RHS) {
+ return LHS->HashValue < RHS->HashValue;
+ });
}
namespace {
@@ -557,8 +555,8 @@ void llvm::emitDWARF5AccelTable(
SmallVector<unsigned, 1> CUIndex(CUs.size());
int Count = 0;
for (const auto &CU : enumerate(CUs)) {
- if (CU.value()->getCUNode()->getNameTableKind() ==
- DICompileUnit::DebugNameTableKind::None)
+ if (CU.value()->getCUNode()->getNameTableKind() !=
+ DICompileUnit::DebugNameTableKind::Default)
continue;
CUIndex[CU.index()] = Count++;
assert(CU.index() == CU.value()->getUniqueID());
@@ -616,30 +614,10 @@ void AppleAccelTableStaticTypeData::emit(AsmPrinter *Asm) const {
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 {
diff --git a/lib/CodeGen/AsmPrinter/AddressPool.cpp b/lib/CodeGen/AsmPrinter/AddressPool.cpp
index 042243b79259..f11c7de5ed8a 100644
--- a/lib/CodeGen/AsmPrinter/AddressPool.cpp
+++ b/lib/CodeGen/AsmPrinter/AddressPool.cpp
@@ -1,9 +1,8 @@
//===- llvm/CodeGen/AddressPool.cpp - Dwarf Debug Framework ---------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
@@ -24,21 +23,24 @@ unsigned AddressPool::getIndex(const MCSymbol *Sym, bool TLS) {
return IterBool.first->second.Number;
}
-
-void AddressPool::emitHeader(AsmPrinter &Asm, MCSection *Section) {
+MCSymbol *AddressPool::emitHeader(AsmPrinter &Asm, MCSection *Section) {
static const uint8_t AddrSize = Asm.getDataLayout().getPointerSize();
- uint64_t Length = sizeof(uint16_t) // version
- + sizeof(uint8_t) // address_size
- + sizeof(uint8_t) // segment_selector_size
- + AddrSize * Pool.size(); // entries
+ StringRef Prefix = "debug_addr_";
+ MCSymbol *BeginLabel = Asm.createTempSymbol(Prefix + "start");
+ MCSymbol *EndLabel = Asm.createTempSymbol(Prefix + "end");
+
Asm.OutStreamer->AddComment("Length of contribution");
- Asm.emitInt32(Length); // TODO: Support DWARF64 format.
+ Asm.EmitLabelDifference(EndLabel, BeginLabel,
+ 4); // TODO: Support DWARF64 format.
+ Asm.OutStreamer->EmitLabel(BeginLabel);
Asm.OutStreamer->AddComment("DWARF version number");
Asm.emitInt16(Asm.getDwarfVersion());
Asm.OutStreamer->AddComment("Address size");
Asm.emitInt8(AddrSize);
Asm.OutStreamer->AddComment("Segment selector size");
Asm.emitInt8(0); // TODO: Support non-zero segment_selector_size.
+
+ return EndLabel;
}
// Emit addresses into the section given.
@@ -49,8 +51,10 @@ void AddressPool::emit(AsmPrinter &Asm, MCSection *AddrSection) {
// Start the dwarf addr section.
Asm.OutStreamer->SwitchSection(AddrSection);
+ MCSymbol *EndLabel = nullptr;
+
if (Asm.getDwarfVersion() >= 5)
- emitHeader(Asm, AddrSection);
+ EndLabel = emitHeader(Asm, AddrSection);
// Define the symbol that marks the start of the contribution.
// It is referenced via DW_AT_addr_base.
@@ -67,4 +71,7 @@ void AddressPool::emit(AsmPrinter &Asm, MCSection *AddrSection) {
for (const MCExpr *Entry : Entries)
Asm.OutStreamer->EmitValue(Entry, Asm.getDataLayout().getPointerSize());
+
+ if (EndLabel)
+ Asm.OutStreamer->EmitLabel(EndLabel);
}
diff --git a/lib/CodeGen/AsmPrinter/AddressPool.h b/lib/CodeGen/AsmPrinter/AddressPool.h
index 2209c7eb50ed..f92cf72093ca 100644
--- a/lib/CodeGen/AsmPrinter/AddressPool.h
+++ b/lib/CodeGen/AsmPrinter/AddressPool.h
@@ -1,9 +1,8 @@
//===- llvm/CodeGen/AddressPool.h - Dwarf Debug Framework -------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
@@ -55,7 +54,7 @@ public:
void setLabel(MCSymbol *Sym) { AddressTableBaseSym = Sym; }
private:
- void emitHeader(AsmPrinter &Asm, MCSection *Section);
+ MCSymbol *emitHeader(AsmPrinter &Asm, MCSection *Section);
/// Symbol designates the start of the contribution to the address table.
MCSymbol *AddressTableBaseSym = nullptr;
diff --git a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
index 7070451e3330..54f6cc2d5571 100644
--- a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -1,9 +1,8 @@
//===- AsmPrinter.cpp - Common AsmPrinter code ----------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -35,7 +34,6 @@
#include "llvm/BinaryFormat/COFF.h"
#include "llvm/BinaryFormat/Dwarf.h"
#include "llvm/BinaryFormat/ELF.h"
-#include "llvm/CodeGen/AsmPrinterHandler.h"
#include "llvm/CodeGen/GCMetadata.h"
#include "llvm/CodeGen/GCMetadataPrinter.h"
#include "llvm/CodeGen/GCStrategy.h"
@@ -60,7 +58,6 @@
#include "llvm/CodeGen/TargetLowering.h"
#include "llvm/CodeGen/TargetOpcodes.h"
#include "llvm/CodeGen/TargetRegisterInfo.h"
-#include "llvm/CodeGen/TargetSubtargetInfo.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/Comdat.h"
#include "llvm/IR/Constant.h"
@@ -80,6 +77,7 @@
#include "llvm/IR/Metadata.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Operator.h"
+#include "llvm/IR/RemarkStreamer.h"
#include "llvm/IR/Type.h"
#include "llvm/IR/Value.h"
#include "llvm/MC/MCAsmInfo.h"
@@ -101,6 +99,9 @@
#include "llvm/MC/MCValue.h"
#include "llvm/MC/SectionKind.h"
#include "llvm/Pass.h"
+#include "llvm/Remarks/Remark.h"
+#include "llvm/Remarks/RemarkFormat.h"
+#include "llvm/Remarks/RemarkStringTable.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Compiler.h"
@@ -143,9 +144,10 @@ static const char *const CodeViewLineTablesGroupDescription =
STATISTIC(EmittedInsts, "Number of machine instrs printed");
-static cl::opt<bool>
- PrintSchedule("print-schedule", cl::Hidden, cl::init(false),
- cl::desc("Print 'sched: [latency:throughput]' in .s output"));
+static cl::opt<bool> EnableRemarksSection(
+ "remarks-section",
+ cl::desc("Emit a section containing remark diagnostics metadata"),
+ cl::init(false));
char AsmPrinter::ID = 0;
@@ -232,6 +234,12 @@ void AsmPrinter::EmitToStreamer(MCStreamer &S, const MCInst &Inst) {
S.EmitInstruction(Inst, getSubtargetInfo());
}
+void AsmPrinter::emitInitialRawDwarfLocDirective(const MachineFunction &MF) {
+ assert(DD && "Dwarf debug file is not defined.");
+ assert(OutStreamer->hasRawTextSupport() && "Expected assembly output mode.");
+ (void)DD->emitInitialLocDirective(MF, /*CUID=*/0);
+}
+
/// getCurrentSection() - Return the current section we are emitting to.
const MCSection *AsmPrinter::getCurrentSection() const {
return OutStreamer->getCurrentSectionOnly();
@@ -252,6 +260,9 @@ bool AsmPrinter::doInitialization(Module &M) {
const_cast<TargetLoweringObjectFile&>(getObjFileLowering())
.Initialize(OutContext, TM);
+ const_cast<TargetLoweringObjectFile &>(getObjFileLowering())
+ .getModuleMetadata(M);
+
OutStreamer->InitSections(false);
// Emit the version-min deployment target directive if needed.
@@ -300,16 +311,17 @@ bool AsmPrinter::doInitialization(Module &M) {
if (MAI->doesSupportDebugInformation()) {
bool EmitCodeView = MMI->getModule()->getCodeViewFlag();
if (EmitCodeView && TM.getTargetTriple().isOSWindows()) {
- Handlers.push_back(HandlerInfo(new CodeViewDebug(this),
- DbgTimerName, DbgTimerDescription,
- CodeViewLineTablesGroupName,
- CodeViewLineTablesGroupDescription));
+ Handlers.emplace_back(llvm::make_unique<CodeViewDebug>(this),
+ DbgTimerName, DbgTimerDescription,
+ CodeViewLineTablesGroupName,
+ CodeViewLineTablesGroupDescription);
}
if (!EmitCodeView || MMI->getModule()->getDwarfVersion()) {
DD = new DwarfDebug(this, &M);
DD->beginModule();
- Handlers.push_back(HandlerInfo(DD, DbgTimerName, DbgTimerDescription,
- DWARFGroupName, DWARFGroupDescription));
+ Handlers.emplace_back(std::unique_ptr<DwarfDebug>(DD), DbgTimerName,
+ DbgTimerDescription, DWARFGroupName,
+ DWARFGroupDescription);
}
}
@@ -362,14 +374,15 @@ bool AsmPrinter::doInitialization(Module &M) {
break;
}
if (ES)
- Handlers.push_back(HandlerInfo(ES, EHTimerName, EHTimerDescription,
- DWARFGroupName, DWARFGroupDescription));
+ Handlers.emplace_back(std::unique_ptr<EHStreamer>(ES), EHTimerName,
+ EHTimerDescription, DWARFGroupName,
+ DWARFGroupDescription);
if (mdconst::extract_or_null<ConstantInt>(
MMI->getModule()->getModuleFlag("cfguardtable")))
- Handlers.push_back(HandlerInfo(new WinCFGuard(this), CFGuardName,
- CFGuardDescription, DWARFGroupName,
- DWARFGroupDescription));
+ Handlers.emplace_back(llvm::make_unique<WinCFGuard>(this), CFGuardName,
+ CFGuardDescription, DWARFGroupName,
+ DWARFGroupDescription);
return false;
}
@@ -483,7 +496,7 @@ void AsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) {
SectionKind GVKind = TargetLoweringObjectFile::getKindForGlobal(GV, TM);
const DataLayout &DL = GV->getParent()->getDataLayout();
- uint64_t Size = DL.getTypeAllocSize(GV->getType()->getElementType());
+ uint64_t Size = DL.getTypeAllocSize(GV->getValueType());
// If the alignment is specified, we *must* obey it. Overaligning a global
// with a specified alignment is a prompt way to break globals emitted to
@@ -658,6 +671,9 @@ void AsmPrinter::EmitFunctionHeader() {
if (MAI->hasDotTypeDotSizeDirective())
OutStreamer->EmitSymbolAttribute(CurrentFnSym, MCSA_ELF_TypeFunction);
+ if (F.hasFnAttribute(Attribute::Cold))
+ OutStreamer->EmitSymbolAttribute(CurrentFnSym, MCSA_Cold);
+
if (isVerbose()) {
F.printAsOperand(OutStreamer->GetCommentOS(),
/*PrintType=*/false, F.getParent());
@@ -738,74 +754,30 @@ void AsmPrinter::EmitFunctionEntryLabel() {
}
/// emitComments - Pretty-print comments for instructions.
-/// It returns true iff the sched comment was emitted.
-/// Otherwise it returns false.
-static bool emitComments(const MachineInstr &MI, raw_ostream &CommentOS,
- AsmPrinter *AP) {
+static void emitComments(const MachineInstr &MI, raw_ostream &CommentOS) {
const MachineFunction *MF = MI.getMF();
const TargetInstrInfo *TII = MF->getSubtarget().getInstrInfo();
// Check for spills and reloads
- int FI;
-
- const MachineFrameInfo &MFI = MF->getFrameInfo();
- bool Commented = false;
-
- auto getSize =
- [&MFI](const SmallVectorImpl<const MachineMemOperand *> &Accesses) {
- unsigned Size = 0;
- for (auto A : Accesses)
- if (MFI.isSpillSlotObjectIndex(
- cast<FixedStackPseudoSourceValue>(A->getPseudoValue())
- ->getFrameIndex()))
- Size += A->getSize();
- return Size;
- };
// We assume a single instruction only has a spill or reload, not
// both.
- const MachineMemOperand *MMO;
- SmallVector<const MachineMemOperand *, 2> Accesses;
- if (TII->isLoadFromStackSlotPostFE(MI, FI)) {
- if (MFI.isSpillSlotObjectIndex(FI)) {
- MMO = *MI.memoperands_begin();
- CommentOS << MMO->getSize() << "-byte Reload";
- Commented = true;
- }
- } else if (TII->hasLoadFromStackSlot(MI, Accesses)) {
- if (auto Size = getSize(Accesses)) {
- CommentOS << Size << "-byte Folded Reload";
- Commented = true;
- }
- } else if (TII->isStoreToStackSlotPostFE(MI, FI)) {
- if (MFI.isSpillSlotObjectIndex(FI)) {
- MMO = *MI.memoperands_begin();
- CommentOS << MMO->getSize() << "-byte Spill";
- Commented = true;
- }
- } else if (TII->hasStoreToStackSlot(MI, Accesses)) {
- if (auto Size = getSize(Accesses)) {
- CommentOS << Size << "-byte Folded Spill";
- Commented = true;
- }
+ Optional<unsigned> Size;
+ if ((Size = MI.getRestoreSize(TII))) {
+ CommentOS << *Size << "-byte Reload\n";
+ } else if ((Size = MI.getFoldedRestoreSize(TII))) {
+ if (*Size)
+ CommentOS << *Size << "-byte Folded Reload\n";
+ } else if ((Size = MI.getSpillSize(TII))) {
+ CommentOS << *Size << "-byte Spill\n";
+ } else if ((Size = MI.getFoldedSpillSize(TII))) {
+ if (*Size)
+ CommentOS << *Size << "-byte Folded Spill\n";
}
// Check for spill-induced copies
- if (MI.getAsmPrinterFlag(MachineInstr::ReloadReuse)) {
- Commented = true;
- CommentOS << " Reload Reuse";
- }
-
- if (Commented) {
- if (AP->EnablePrintSchedInfo) {
- // If any comment was added above and we need sched info comment then add
- // this new comment just after the above comment w/o "\n" between them.
- CommentOS << " " << MF->getSubtarget().getSchedInfoStr(MI) << "\n";
- return true;
- }
- CommentOS << "\n";
- }
- return false;
+ if (MI.getAsmPrinterFlag(MachineInstr::ReloadReuse))
+ CommentOS << " Reload Reuse\n";
}
/// emitImplicitDef - This method emits the specified machine instruction
@@ -1093,10 +1065,8 @@ void AsmPrinter::EmitFunctionBody() {
}
}
- if (isVerbose() && emitComments(MI, OutStreamer->GetCommentOS(), this)) {
- MachineInstr *MIP = const_cast<MachineInstr *>(&MI);
- MIP->setAsmPrinterFlag(MachineInstr::NoSchedComment);
- }
+ if (isVerbose())
+ emitComments(MI, OutStreamer->GetCommentOS());
switch (MI.getOpcode()) {
case TargetOpcode::CFI_INSTRUCTION:
@@ -1105,11 +1075,13 @@ void AsmPrinter::EmitFunctionBody() {
case TargetOpcode::LOCAL_ESCAPE:
emitFrameAlloc(MI);
break;
+ case TargetOpcode::ANNOTATION_LABEL:
case TargetOpcode::EH_LABEL:
case TargetOpcode::GC_LABEL:
OutStreamer->EmitLabel(MI.getOperand(0).getMCSymbol());
break;
case TargetOpcode::INLINEASM:
+ case TargetOpcode::INLINEASM_BR:
EmitInlineAsm(&MI);
break;
case TargetOpcode::DBG_VALUE:
@@ -1266,7 +1238,7 @@ static bool isGOTEquivalentCandidate(const GlobalVariable *GV,
// GlobalVariable or Function, i.e., as GlobalValue.
if (!GV->hasGlobalUnnamedAddr() || !GV->hasInitializer() ||
!GV->isConstant() || !GV->isDiscardableIfUnused() ||
- !dyn_cast<GlobalValue>(GV->getOperand(0)))
+ !isa<GlobalValue>(GV->getOperand(0)))
return false;
// To be a got equivalent, at least one of its users need to be a constant
@@ -1329,9 +1301,19 @@ void AsmPrinter::emitGlobalIndirectSymbol(Module &M,
else
assert(GIS.hasLocalLinkage() && "Invalid alias or ifunc linkage");
+ bool IsFunction = GIS.getValueType()->isFunctionTy();
+
+ // Treat bitcasts of functions as functions also. This is important at least
+ // on WebAssembly where object and function addresses can't alias each other.
+ if (!IsFunction)
+ if (auto *CE = dyn_cast<ConstantExpr>(GIS.getIndirectSymbol()))
+ if (CE->getOpcode() == Instruction::BitCast)
+ IsFunction =
+ CE->getOperand(0)->getType()->getPointerElementType()->isFunctionTy();
+
// Set the symbol type to function if the alias has a function type.
// This affects codegen when the aliasee is not a function.
- if (GIS.getType()->getPointerElementType()->isFunctionTy()) {
+ if (IsFunction) {
OutStreamer->EmitSymbolAttribute(Name, MCSA_ELF_TypeFunction);
if (isa<GlobalIFunc>(GIS))
OutStreamer->EmitSymbolAttribute(Name, MCSA_ELF_TypeIndFunction);
@@ -1363,6 +1345,66 @@ void AsmPrinter::emitGlobalIndirectSymbol(Module &M,
}
}
+void AsmPrinter::emitRemarksSection(Module &M) {
+ RemarkStreamer *RS = M.getContext().getRemarkStreamer();
+ if (!RS)
+ return;
+ const remarks::Serializer &Serializer = RS->getSerializer();
+
+ // Switch to the right section: .remarks/__remarks.
+ MCSection *RemarksSection =
+ OutContext.getObjectFileInfo()->getRemarksSection();
+ OutStreamer->SwitchSection(RemarksSection);
+
+ // Emit the magic number.
+ OutStreamer->EmitBytes(remarks::Magic);
+ // Explicitly emit a '\0'.
+ OutStreamer->EmitIntValue(/*Value=*/0, /*Size=*/1);
+
+ // Emit the version number: little-endian uint64_t.
+ // The version number is located at the offset 0x0 in the section.
+ std::array<char, 8> Version;
+ support::endian::write64le(Version.data(), remarks::Version);
+ OutStreamer->EmitBinaryData(StringRef(Version.data(), Version.size()));
+
+ // Emit the string table in the section.
+ // Note: we need to use the streamer here to emit it in the section. We can't
+ // just use the serialize function with a raw_ostream because of the way
+ // MCStreamers work.
+ uint64_t StrTabSize =
+ Serializer.StrTab ? Serializer.StrTab->SerializedSize : 0;
+ // Emit the total size of the string table (the size itself excluded):
+ // little-endian uint64_t.
+ // The total size is located after the version number.
+ // Note: even if no string table is used, emit 0.
+ std::array<char, 8> StrTabSizeBuf;
+ support::endian::write64le(StrTabSizeBuf.data(), StrTabSize);
+ OutStreamer->EmitBinaryData(
+ StringRef(StrTabSizeBuf.data(), StrTabSizeBuf.size()));
+
+ if (const Optional<remarks::StringTable> &StrTab = Serializer.StrTab) {
+ std::vector<StringRef> StrTabStrings = StrTab->serialize();
+ // Emit a list of null-terminated strings.
+ // Note: the order is important here: the ID used in the remarks corresponds
+ // to the position of the string in the section.
+ for (StringRef Str : StrTabStrings) {
+ OutStreamer->EmitBytes(Str);
+ // Explicitly emit a '\0'.
+ OutStreamer->EmitIntValue(/*Value=*/0, /*Size=*/1);
+ }
+ }
+
+ // Emit the null-terminated absolute path to the remark file.
+ // The path is located at the offset 0x4 in the section.
+ StringRef FilenameRef = RS->getFilename();
+ SmallString<128> Filename = FilenameRef;
+ sys::fs::make_absolute(Filename);
+ assert(!Filename.empty() && "The filename can't be empty.");
+ OutStreamer->EmitBytes(Filename);
+ // Explicitly emit a '\0'.
+ OutStreamer->EmitIntValue(/*Value=*/0, /*Size=*/1);
+}
+
bool AsmPrinter::doFinalization(Module &M) {
// Set the MachineFunction to nullptr so that we can catch attempted
// accesses to MF specific features at the module level and so that
@@ -1394,6 +1436,12 @@ bool AsmPrinter::doFinalization(Module &M) {
EmitVisibility(Name, V, false);
}
+ // Emit the remarks section contents.
+ // FIXME: Figure out when is the safest time to emit this section. It should
+ // not come after debug info.
+ if (EnableRemarksSection)
+ emitRemarksSection(M);
+
const TargetLoweringObjectFile &TLOF = getObjFileLowering();
TLOF.emitModuleMetadata(*OutStreamer, M);
@@ -1448,7 +1496,6 @@ bool AsmPrinter::doFinalization(Module &M) {
NamedRegionTimer T(HI.TimerName, HI.TimerDescription, HI.TimerGroupName,
HI.TimerGroupDescription, TimePassesIsEnabled);
HI.Handler->endModule();
- delete HI.Handler;
}
Handlers.clear();
DD = nullptr;
@@ -1592,6 +1639,24 @@ bool AsmPrinter::doFinalization(Module &M) {
OutStreamer->EmitAddrsigSym(getSymbol(&GV));
}
+ // Emit symbol partition specifications (ELF only).
+ if (TM.getTargetTriple().isOSBinFormatELF()) {
+ unsigned UniqueID = 0;
+ for (const GlobalValue &GV : M.global_values()) {
+ if (!GV.hasPartition() || GV.isDeclarationForLinker() ||
+ GV.getVisibility() != GlobalValue::DefaultVisibility)
+ continue;
+
+ OutStreamer->SwitchSection(OutContext.getELFSection(
+ ".llvm_sympart", ELF::SHT_LLVM_SYMPART, 0, 0, "", ++UniqueID));
+ OutStreamer->EmitBytes(GV.getPartition());
+ OutStreamer->EmitZeros(1);
+ OutStreamer->EmitValue(
+ MCSymbolRefExpr::create(getSymbol(&GV), OutContext),
+ MAI->getCodePointerSize());
+ }
+ }
+
// Allow the target to emit any magic that it wants at the end of the file,
// after everything else has gone out.
EmitEndOfAsmFile(M);
@@ -1628,11 +1693,6 @@ void AsmPrinter::SetupMachineFunction(MachineFunction &MF) {
}
ORE = &getAnalysis<MachineOptimizationRemarkEmitterPass>().getORE();
-
- const TargetSubtargetInfo &STI = MF.getSubtarget();
- EnablePrintSchedInfo = PrintSchedule.getNumOccurrences()
- ? PrintSchedule
- : STI.supportPrintSchedInfo();
}
namespace {
@@ -1905,8 +1965,7 @@ bool AsmPrinter::EmitSpecialLLVMGlobal(const GlobalVariable *GV) {
}
/// EmitLLVMUsedList - For targets that define a MAI::UsedDirective, mark each
-/// global in the specified llvm.used list for which emitUsedDirectiveFor
-/// is true, as being used with this directive.
+/// global in the specified llvm.used list.
void AsmPrinter::EmitLLVMUsedList(const ConstantArray *InitList) {
// Should be an array of 'i8*'.
for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) {
@@ -1933,7 +1992,7 @@ struct Structor {
/// priority.
void AsmPrinter::EmitXXStructorList(const DataLayout &DL, const Constant *List,
bool isCtor) {
- // Should be an array of '{ int, void ()* }' structs. The first value is the
+ // Should be an array of '{ i32, void ()*, i8* }' structs. The first value is the
// init priority.
if (!isa<ConstantArray>(List)) return;
@@ -1941,12 +2000,10 @@ void AsmPrinter::EmitXXStructorList(const DataLayout &DL, const Constant *List,
const ConstantArray *InitList = dyn_cast<ConstantArray>(List);
if (!InitList) return; // Not an array!
StructType *ETy = dyn_cast<StructType>(InitList->getType()->getElementType());
- // FIXME: Only allow the 3-field form in LLVM 4.0.
- if (!ETy || ETy->getNumElements() < 2 || ETy->getNumElements() > 3)
- return; // Not an array of two or three elements!
- if (!isa<IntegerType>(ETy->getTypeAtIndex(0U)) ||
- !isa<PointerType>(ETy->getTypeAtIndex(1U))) return; // Not (int, ptr).
- if (ETy->getNumElements() == 3 && !isa<PointerType>(ETy->getTypeAtIndex(2U)))
+ if (!ETy || ETy->getNumElements() != 3 ||
+ !isa<IntegerType>(ETy->getTypeAtIndex(0U)) ||
+ !isa<PointerType>(ETy->getTypeAtIndex(1U)) ||
+ !isa<PointerType>(ETy->getTypeAtIndex(2U)))
return; // Not (int, ptr, ptr).
// Gather the structors in a form that's convenient for sorting by priority.
@@ -1962,16 +2019,16 @@ void AsmPrinter::EmitXXStructorList(const DataLayout &DL, const Constant *List,
Structor &S = Structors.back();
S.Priority = Priority->getLimitedValue(65535);
S.Func = CS->getOperand(1);
- if (ETy->getNumElements() == 3 && !CS->getOperand(2)->isNullValue())
+ if (!CS->getOperand(2)->isNullValue())
S.ComdatKey =
dyn_cast<GlobalValue>(CS->getOperand(2)->stripPointerCasts());
}
// Emit the function pointers in the target-specific order
unsigned Align = Log2_32(DL.getPointerPrefAlignment());
- std::stable_sort(Structors.begin(), Structors.end(),
- [](const Structor &L,
- const Structor &R) { return L.Priority < R.Priority; });
+ llvm::stable_sort(Structors, [](const Structor &L, const Structor &R) {
+ return L.Priority < R.Priority;
+ });
for (Structor &S : Structors) {
const TargetLoweringObjectFile &Obj = getObjFileLowering();
const MCSymbol *KeySym = nullptr;
@@ -2199,7 +2256,10 @@ const MCExpr *AsmPrinter::lowerConstant(const Constant *CV) {
// We can emit the pointer value into this slot if the slot is an
// integer slot equal to the size of the pointer.
- if (DL.getTypeAllocSize(Ty) == DL.getTypeAllocSize(Op->getType()))
+ //
+ // If the pointer is larger than the resultant integer, then
+ // as with Trunc just depend on the assembler to truncate it.
+ if (DL.getTypeAllocSize(Ty) <= DL.getTypeAllocSize(Op->getType()))
return OpExpr;
// Otherwise the pointer is smaller than the resultant integer, mask off
@@ -2740,7 +2800,7 @@ 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()) {
+ if (getSubtargetInfo().getTargetTriple().isWindowsMSVCEnvironment()) {
const MachineConstantPoolEntry &CPE =
MF->getConstantPool()->getConstants()[CPID];
if (!CPE.isMachineConstantPoolEntry()) {
@@ -2858,7 +2918,7 @@ void AsmPrinter::setupCodePaddingContext(const MachineBasicBlock &MBB,
MCCodePaddingContext &Context) const {
assert(MF != nullptr && "Machine function must be valid");
Context.IsPaddingActive = !MF->hasInlineAsm() &&
- !MF->getFunction().optForSize() &&
+ !MF->getFunction().hasOptSize() &&
TM.getOptLevel() != CodeGenOpt::None;
Context.IsBasicBlockReachableViaFallthrough =
std::find(MBB.pred_begin(), MBB.pred_end(), MBB.getPrevNode()) !=
@@ -2918,13 +2978,16 @@ void AsmPrinter::EmitBasicBlockStart(const MachineBasicBlock &MBB) const {
// Print the main label for the block.
if (MBB.pred_empty() ||
- (isBlockOnlyReachableByFallthrough(&MBB) && !MBB.isEHFuncletEntry())) {
+ (isBlockOnlyReachableByFallthrough(&MBB) && !MBB.isEHFuncletEntry() &&
+ !MBB.hasLabelMustBeEmitted())) {
if (isVerbose()) {
// NOTE: Want this comment at start of line, don't emit with AddComment.
OutStreamer->emitRawComment(" %bb." + Twine(MBB.getNumber()) + ":",
false);
}
} else {
+ if (isVerbose() && MBB.hasLabelMustBeEmitted())
+ OutStreamer->AddComment("Label of block must be emitted");
OutStreamer->EmitLabel(MBB.getSymbol());
}
}
diff --git a/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp b/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp
index afce3ad3133b..992e44d95306 100644
--- a/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp
+++ b/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp
@@ -1,9 +1,8 @@
//===-- AsmPrinterDwarf.cpp - AsmPrinter Dwarf Support --------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -19,6 +18,7 @@
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/MC/MCDwarf.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/MCSection.h"
#include "llvm/MC/MCStreamer.h"
@@ -43,11 +43,11 @@ void AsmPrinter::EmitSLEB128(int64_t Value, const char *Desc) const {
OutStreamer->EmitSLEB128IntValue(Value);
}
-void AsmPrinter::EmitULEB128(uint64_t Value, const char *Desc) const {
+void AsmPrinter::EmitULEB128(uint64_t Value, const char *Desc, unsigned PadTo) const {
if (isVerbose() && Desc)
OutStreamer->AddComment(Desc);
- OutStreamer->EmitULEB128IntValue(Value);
+ OutStreamer->EmitULEB128IntValue(Value, PadTo);
}
/// Emit something like ".uleb128 Hi-Lo".
@@ -183,6 +183,25 @@ void AsmPrinter::EmitDwarfOffset(const MCSymbol *Label, uint64_t Offset) const {
EmitLabelPlusOffset(Label, Offset, MAI->getCodePointerSize());
}
+void AsmPrinter::EmitCallSiteOffset(const MCSymbol *Hi,
+ const MCSymbol *Lo,
+ unsigned Encoding) const {
+ // The least significant 3 bits specify the width of the encoding
+ if ((Encoding & 0x7) == dwarf::DW_EH_PE_uleb128)
+ EmitLabelDifferenceAsULEB128(Hi, Lo);
+ else
+ EmitLabelDifference(Hi, Lo, GetSizeOfEncodedValue(Encoding));
+}
+
+void AsmPrinter::EmitCallSiteValue(uint64_t Value,
+ unsigned Encoding) const {
+ // The least significant 3 bits specify the width of the encoding
+ if ((Encoding & 0x7) == dwarf::DW_EH_PE_uleb128)
+ EmitULEB128(Value);
+ else
+ OutStreamer->EmitIntValue(Value, GetSizeOfEncodedValue(Encoding));
+}
+
//===----------------------------------------------------------------------===//
// Dwarf Lowering Routines
//===----------------------------------------------------------------------===//
diff --git a/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp b/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp
index 62103e3107c0..7721e996aca5 100644
--- a/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp
+++ b/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp
@@ -1,9 +1,8 @@
//===-- AsmPrinterInlineAsm.cpp - AsmPrinter Inline Asm Handling ----------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -19,7 +18,6 @@
#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/CodeGen/TargetInstrInfo.h"
#include "llvm/CodeGen/TargetRegisterInfo.h"
-#include "llvm/CodeGen/TargetSubtargetInfo.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/InlineAsm.h"
@@ -155,15 +153,10 @@ void AsmPrinter::EmitInlineAsm(StringRef Str, const MCSubtargetInfo &STI,
" we don't have an asm parser for this target\n");
Parser->setAssemblerDialect(Dialect);
Parser->setTargetParser(*TAP.get());
- Parser->setEnablePrintSchedInfo(EnablePrintSchedInfo);
// Enable lexing Masm binary and hex integer literals in intel inline
// assembly.
if (Dialect == InlineAsm::AD_Intel)
Parser->getLexer().setLexMasmIntegers(true);
- if (MF) {
- const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo();
- TAP->SetFrameRegister(TRI->getFrameRegister(*MF));
- }
emitInlineAsmStart();
// Don't implicitly switch to the text section before the asm.
@@ -176,9 +169,8 @@ void AsmPrinter::EmitInlineAsm(StringRef Str, const MCSubtargetInfo &STI,
}
static void EmitMSInlineAsmStr(const char *AsmStr, const MachineInstr *MI,
- MachineModuleInfo *MMI, int InlineAsmVariant,
- AsmPrinter *AP, unsigned LocCookie,
- raw_ostream &OS) {
+ MachineModuleInfo *MMI, AsmPrinter *AP,
+ unsigned LocCookie, raw_ostream &OS) {
// Switch to the inline assembly variant.
OS << "\t.intel_syntax\n\t";
@@ -270,11 +262,9 @@ static void EmitMSInlineAsmStr(const char *AsmStr, const MachineInstr *MI,
++OpNo; // Skip over the ID number.
if (InlineAsm::isMemKind(OpFlags)) {
- Error = AP->PrintAsmMemoryOperand(MI, OpNo, InlineAsmVariant,
- /*Modifier*/ nullptr, OS);
+ Error = AP->PrintAsmMemoryOperand(MI, OpNo, /*Modifier*/ nullptr, OS);
} else {
- Error = AP->PrintAsmOperand(MI, OpNo, InlineAsmVariant,
- /*Modifier*/ nullptr, OS);
+ Error = AP->PrintAsmOperand(MI, OpNo, /*Modifier*/ nullptr, OS);
}
}
if (Error) {
@@ -291,9 +281,9 @@ static void EmitMSInlineAsmStr(const char *AsmStr, const MachineInstr *MI,
}
static void EmitGCCInlineAsmStr(const char *AsmStr, const MachineInstr *MI,
- MachineModuleInfo *MMI, int InlineAsmVariant,
- int AsmPrinterVariant, AsmPrinter *AP,
- unsigned LocCookie, raw_ostream &OS) {
+ MachineModuleInfo *MMI, int AsmPrinterVariant,
+ AsmPrinter *AP, unsigned LocCookie,
+ raw_ostream &OS) {
int CurVariant = -1; // The number of the {.|.|.} region we are in.
const char *LastEmitted = AsmStr; // One past the last character emitted.
unsigned NumOperands = MI->getNumOperands();
@@ -435,17 +425,25 @@ static void EmitGCCInlineAsmStr(const char *AsmStr, const MachineInstr *MI,
unsigned OpFlags = MI->getOperand(OpNo).getImm();
++OpNo; // Skip over the ID number.
+ // FIXME: Shouldn't arch-independent output template handling go into
+ // PrintAsmOperand?
if (Modifier[0] == 'l') { // Labels are target independent.
- // FIXME: What if the operand isn't an MBB, report error?
- const MCSymbol *Sym = MI->getOperand(OpNo).getMBB()->getSymbol();
- Sym->print(OS, AP->MAI);
+ if (MI->getOperand(OpNo).isBlockAddress()) {
+ const BlockAddress *BA = MI->getOperand(OpNo).getBlockAddress();
+ MCSymbol *Sym = AP->GetBlockAddressSymbol(BA);
+ Sym->print(OS, AP->MAI);
+ } else if (MI->getOperand(OpNo).isMBB()) {
+ const MCSymbol *Sym = MI->getOperand(OpNo).getMBB()->getSymbol();
+ Sym->print(OS, AP->MAI);
+ } else {
+ Error = true;
+ }
} else {
if (InlineAsm::isMemKind(OpFlags)) {
- Error = AP->PrintAsmMemoryOperand(MI, OpNo, InlineAsmVariant,
- Modifier[0] ? Modifier : nullptr,
- OS);
+ Error = AP->PrintAsmMemoryOperand(
+ MI, OpNo, Modifier[0] ? Modifier : nullptr, OS);
} else {
- Error = AP->PrintAsmOperand(MI, OpNo, InlineAsmVariant,
+ Error = AP->PrintAsmOperand(MI, OpNo,
Modifier[0] ? Modifier : nullptr, OS);
}
}
@@ -515,18 +513,11 @@ void AsmPrinter::EmitInlineAsm(const MachineInstr *MI) const {
// The variant of the current asmprinter.
int AsmPrinterVariant = MAI->getAssemblerDialect();
- InlineAsm::AsmDialect InlineAsmVariant = MI->getInlineAsmDialect();
AsmPrinter *AP = const_cast<AsmPrinter*>(this);
- if (InlineAsmVariant == InlineAsm::AD_ATT)
- EmitGCCInlineAsmStr(AsmStr, MI, MMI, InlineAsmVariant, AsmPrinterVariant,
- AP, LocCookie, OS);
+ if (MI->getInlineAsmDialect() == InlineAsm::AD_ATT)
+ EmitGCCInlineAsmStr(AsmStr, MI, MMI, AsmPrinterVariant, AP, LocCookie, OS);
else
- EmitMSInlineAsmStr(AsmStr, MI, MMI, InlineAsmVariant, AP, LocCookie, OS);
-
- // Reset SanitizeAddress based on the function's attribute.
- MCTargetOptions MCOptions = TM.Options.MCOptions;
- MCOptions.SanitizeAddress =
- MF->getFunction().hasFnAttribute(Attribute::SanitizeAddress);
+ EmitMSInlineAsmStr(AsmStr, MI, MMI, AP, LocCookie, OS);
// Emit warnings if we use reserved registers on the clobber list, as
// that might give surprising results.
@@ -566,7 +557,7 @@ void AsmPrinter::EmitInlineAsm(const MachineInstr *MI) const {
SrcMgr.PrintMessage(Loc, SourceMgr::DK_Note, Note);
}
- EmitInlineAsm(OS.str(), getSubtargetInfo(), MCOptions, LocMD,
+ EmitInlineAsm(OS.str(), getSubtargetInfo(), TM.Options.MCOptions, LocMD,
MI->getInlineAsmDialect());
// Emit the #NOAPP end marker. This has to happen even if verbose-asm isn't
@@ -608,32 +599,50 @@ void AsmPrinter::PrintSpecial(const MachineInstr *MI, raw_ostream &OS,
}
}
+void AsmPrinter::PrintSymbolOperand(const MachineOperand &MO, raw_ostream &OS) {
+ assert(MO.isGlobal() && "caller should check MO.isGlobal");
+ getSymbol(MO.getGlobal())->print(OS, MAI);
+ printOffset(MO.getOffset(), OS);
+}
+
/// PrintAsmOperand - Print the specified operand of MI, an INLINEASM
/// instruction, using the specified assembler variant. Targets should
-/// override this to format as appropriate.
+/// override this to format as appropriate for machine specific ExtraCodes
+/// or when the arch-independent handling would be too complex otherwise.
bool AsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
- unsigned AsmVariant, const char *ExtraCode,
- raw_ostream &O) {
+ const char *ExtraCode, raw_ostream &O) {
// Does this asm operand have a single letter operand modifier?
if (ExtraCode && ExtraCode[0]) {
if (ExtraCode[1] != 0) return true; // Unknown modifier.
+ // https://gcc.gnu.org/onlinedocs/gccint/Output-Template.html
const MachineOperand &MO = MI->getOperand(OpNo);
switch (ExtraCode[0]) {
default:
return true; // Unknown modifier.
+ case 'a': // Print as memory address.
+ if (MO.isReg()) {
+ PrintAsmMemoryOperand(MI, OpNo, nullptr, O);
+ return false;
+ }
+ LLVM_FALLTHROUGH; // GCC allows '%a' to behave like '%c' with immediates.
case 'c': // Substitute immediate value without immediate syntax
- if (MO.getType() != MachineOperand::MO_Immediate)
- return true;
- O << MO.getImm();
- return false;
+ if (MO.isImm()) {
+ O << MO.getImm();
+ return false;
+ }
+ if (MO.isGlobal()) {
+ PrintSymbolOperand(MO, O);
+ return false;
+ }
+ return true;
case 'n': // Negate the immediate constant.
- if (MO.getType() != MachineOperand::MO_Immediate)
+ if (!MO.isImm())
return true;
O << -MO.getImm();
return false;
case 's': // The GCC deprecated s modifier
- if (MO.getType() != MachineOperand::MO_Immediate)
+ if (!MO.isImm())
return true;
O << ((32 - MO.getImm()) & 31);
return false;
@@ -643,7 +652,6 @@ bool AsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
}
bool AsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
- unsigned AsmVariant,
const char *ExtraCode, raw_ostream &O) {
// Target doesn't support this yet!
return true;
diff --git a/lib/CodeGen/AsmPrinter/ByteStreamer.h b/lib/CodeGen/AsmPrinter/ByteStreamer.h
index 2163cc7e3e11..db2ff458eb2e 100644
--- a/lib/CodeGen/AsmPrinter/ByteStreamer.h
+++ b/lib/CodeGen/AsmPrinter/ByteStreamer.h
@@ -1,9 +1,8 @@
//===-- llvm/CodeGen/ByteStreamer.h - ByteStreamer class --------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -32,7 +31,7 @@ class ByteStreamer {
// For now we're just handling the calls we need for dwarf emission/hashing.
virtual void EmitInt8(uint8_t Byte, const Twine &Comment = "") = 0;
virtual void EmitSLEB128(uint64_t DWord, const Twine &Comment = "") = 0;
- virtual void EmitULEB128(uint64_t DWord, const Twine &Comment = "") = 0;
+ virtual void EmitULEB128(uint64_t DWord, const Twine &Comment = "", unsigned PadTo = 0) = 0;
};
class APByteStreamer final : public ByteStreamer {
@@ -49,7 +48,7 @@ public:
AP.OutStreamer->AddComment(Comment);
AP.EmitSLEB128(DWord);
}
- void EmitULEB128(uint64_t DWord, const Twine &Comment) override {
+ void EmitULEB128(uint64_t DWord, const Twine &Comment, unsigned PadTo) override {
AP.OutStreamer->AddComment(Comment);
AP.EmitULEB128(DWord);
}
@@ -66,7 +65,7 @@ class HashingByteStreamer final : public ByteStreamer {
void EmitSLEB128(uint64_t DWord, const Twine &Comment) override {
Hash.addSLEB128(DWord);
}
- void EmitULEB128(uint64_t DWord, const Twine &Comment) override {
+ void EmitULEB128(uint64_t DWord, const Twine &Comment, unsigned PadTo) override {
Hash.addULEB128(DWord);
}
};
@@ -103,9 +102,9 @@ public:
}
}
- void EmitULEB128(uint64_t DWord, const Twine &Comment) override {
+ void EmitULEB128(uint64_t DWord, const Twine &Comment, unsigned PadTo) override {
raw_svector_ostream OSE(Buffer);
- unsigned Length = encodeULEB128(DWord, OSE);
+ unsigned Length = encodeULEB128(DWord, OSE, PadTo);
if (GenerateComments) {
Comments.push_back(Comment.str());
// Add some empty comments to keep the Buffer and Comments vectors aligned
diff --git a/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp b/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
index 8cabad4ad312..932959c311fa 100644
--- a/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
+++ b/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
@@ -1,9 +1,8 @@
//===- llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp ----------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -42,6 +41,7 @@
#include "llvm/Config/llvm-config.h"
#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
#include "llvm/DebugInfo/CodeView/CodeView.h"
+#include "llvm/DebugInfo/CodeView/CodeViewRecordIO.h"
#include "llvm/DebugInfo/CodeView/ContinuationRecordBuilder.h"
#include "llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h"
#include "llvm/DebugInfo/CodeView/EnumTables.h"
@@ -51,6 +51,7 @@
#include "llvm/DebugInfo/CodeView/TypeIndex.h"
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
#include "llvm/DebugInfo/CodeView/TypeTableCollection.h"
+#include "llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/DebugInfoMetadata.h"
@@ -67,6 +68,7 @@
#include "llvm/MC/MCSymbol.h"
#include "llvm/Support/BinaryByteStream.h"
#include "llvm/Support/BinaryStreamReader.h"
+#include "llvm/Support/BinaryStreamWriter.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Compiler.h"
@@ -93,6 +95,26 @@
using namespace llvm;
using namespace llvm::codeview;
+namespace {
+class CVMCAdapter : public CodeViewRecordStreamer {
+public:
+ CVMCAdapter(MCStreamer &OS) : OS(&OS) {}
+
+ void EmitBytes(StringRef Data) { OS->EmitBytes(Data); }
+
+ void EmitIntValue(uint64_t Value, unsigned Size) {
+ OS->EmitIntValueInHex(Value, Size);
+ }
+
+ void EmitBinaryData(StringRef Data) { OS->EmitBinaryData(Data); }
+
+ void AddComment(const Twine &T) { OS->AddComment(T); }
+
+private:
+ MCStreamer *OS = nullptr;
+};
+} // namespace
+
static CPUType mapArchToCVCPUType(Triple::ArchType Type) {
switch (Type) {
case Triple::ArchType::x86:
@@ -273,7 +295,7 @@ static const DISubprogram *getQualifiedNameComponents(
StringRef ScopeName = getPrettyScopeName(Scope);
if (!ScopeName.empty())
QualifiedNameComponents.push_back(ScopeName);
- Scope = Scope->getScope().resolve();
+ Scope = Scope->getScope();
}
return ClosestSubprogram;
}
@@ -309,7 +331,7 @@ struct CodeViewDebug::TypeLoweringScope {
};
static std::string getFullyQualifiedName(const DIScope *Ty) {
- const DIScope *Scope = Ty->getScope().resolve();
+ const DIScope *Scope = Ty->getScope();
return getFullyQualifiedName(Scope, getPrettyScopeName(Ty));
}
@@ -344,7 +366,7 @@ TypeIndex CodeViewDebug::getFuncIdForSubprogram(const DISubprogram *SP) {
// MSVC.
StringRef DisplayName = SP->getName().split('<').first;
- const DIScope *Scope = SP->getScope().resolve();
+ const DIScope *Scope = SP->getScope();
TypeIndex TI;
if (const auto *Class = dyn_cast_or_null<DICompositeType>(Scope)) {
// If the scope is a DICompositeType, then this must be a method. Member
@@ -364,8 +386,8 @@ TypeIndex CodeViewDebug::getFuncIdForSubprogram(const DISubprogram *SP) {
return recordTypeIndexForDINode(SP, TI);
}
-static bool isTrivial(const DICompositeType *DCTy) {
- return ((DCTy->getFlags() & DINode::FlagTrivial) == DINode::FlagTrivial);
+static bool isNonTrivial(const DICompositeType *DCTy) {
+ return ((DCTy->getFlags() & DINode::FlagNonTrivial) == DINode::FlagNonTrivial);
}
static FunctionOptions
@@ -376,16 +398,16 @@ getFunctionOptions(const DISubroutineType *Ty,
const DIType *ReturnTy = nullptr;
if (auto TypeArray = Ty->getTypeArray()) {
if (TypeArray.size())
- ReturnTy = TypeArray[0].resolve();
+ ReturnTy = TypeArray[0];
}
if (auto *ReturnDCTy = dyn_cast_or_null<DICompositeType>(ReturnTy)) {
- if (!isTrivial(ReturnDCTy))
+ if (isNonTrivial(ReturnDCTy))
FO |= FunctionOptions::CxxReturnUdt;
}
// DISubroutineType is unnamed. Use DISubprogram's i.e. SPName in comparison.
- if (ClassTy && !isTrivial(ClassTy) && SPName == ClassTy->getName()) {
+ if (ClassTy && isNonTrivial(ClassTy) && SPName == ClassTy->getName()) {
FO |= FunctionOptions::Constructor;
// TODO: put the FunctionOptions::ConstructorWithVirtualBases flag.
@@ -582,8 +604,9 @@ void CodeViewDebug::endModule() {
clear();
}
-static void emitNullTerminatedSymbolName(MCStreamer &OS, StringRef S,
- unsigned MaxFixedRecordLength = 0xF00) {
+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
@@ -594,6 +617,13 @@ static void emitNullTerminatedSymbolName(MCStreamer &OS, StringRef S,
OS.EmitBytes(NullTerminatedString);
}
+static StringRef getTypeLeafName(TypeLeafKind TypeKind) {
+ for (const EnumEntry<TypeLeafKind> &EE : getTypeLeafNames())
+ if (EE.Value == TypeKind)
+ return EE.Name;
+ return "";
+}
+
void CodeViewDebug::emitTypeInformation() {
if (TypeTable.empty())
return;
@@ -610,31 +640,55 @@ void CodeViewDebug::emitTypeInformation() {
}
TypeTableCollection Table(TypeTable.records());
+ SmallString<512> CommentBlock;
+ raw_svector_ostream CommentOS(CommentBlock);
+ std::unique_ptr<ScopedPrinter> SP;
+ std::unique_ptr<TypeDumpVisitor> TDV;
+ TypeVisitorCallbackPipeline Pipeline;
+
+ if (OS.isVerboseAsm()) {
+ // To construct block comment describing the type record for readability.
+ SP = llvm::make_unique<ScopedPrinter>(CommentOS);
+ SP->setPrefix(CommentPrefix);
+ TDV = llvm::make_unique<TypeDumpVisitor>(Table, SP.get(), false);
+ Pipeline.addCallbackToPipeline(*TDV);
+ }
+
+ // To emit type record using Codeview MCStreamer adapter
+ CVMCAdapter CVMCOS(OS);
+ TypeRecordMapping typeMapping(CVMCOS);
+ Pipeline.addCallbackToPipeline(typeMapping);
+
Optional<TypeIndex> B = Table.getFirst();
while (B) {
// This will fail if the record data is invalid.
CVType Record = Table.getType(*B);
+ CommentBlock.clear();
+
+ auto RecordLen = Record.length();
+ auto RecordKind = Record.kind();
+ if (OS.isVerboseAsm())
+ CVMCOS.AddComment("Record length");
+ CVMCOS.EmitIntValue(RecordLen - 2, 2);
+ if (OS.isVerboseAsm())
+ CVMCOS.AddComment("Record kind: " + getTypeLeafName(RecordKind));
+ CVMCOS.EmitIntValue(RecordKind, sizeof(RecordKind));
+
+ Error E = codeview::visitTypeRecord(Record, *B, Pipeline);
+
+ if (E) {
+ logAllUnhandledErrors(std::move(E), errs(), "error: ");
+ llvm_unreachable("produced malformed type record");
+ }
+
if (OS.isVerboseAsm()) {
- // Emit a block comment describing the type record for readability.
- SmallString<512> CommentBlock;
- raw_svector_ostream CommentOS(CommentBlock);
- ScopedPrinter SP(CommentOS);
- SP.setPrefix(CommentPrefix);
- TypeDumpVisitor TDV(Table, &SP, false);
-
- Error E = codeview::visitTypeRecord(Record, *B, TDV);
- if (E) {
- logAllUnhandledErrors(std::move(E), errs(), "error: ");
- llvm_unreachable("produced malformed type record");
- }
// emitRawComment will insert its own tab and comment string before
// the first line, so strip off our first one. It also prints its own
// newline.
OS.emitRawComment(
CommentOS.str().drop_front(CommentPrefix.size() - 1).rtrim());
}
- OS.EmitBinaryData(Record.str_data());
B = Table.getNext(*B);
}
}
@@ -700,6 +754,8 @@ static SourceLanguage MapDWLangToCVLang(unsigned DWLang) {
return SourceLanguage::Java;
case dwarf::DW_LANG_D:
return SourceLanguage::D;
+ case dwarf::DW_LANG_Swift:
+ return SourceLanguage::Swift;
default:
// There's no CodeView representation for this language, and CV doesn't
// have an "unknown" option for the language field, so we'll use MASM,
@@ -973,8 +1029,7 @@ void CodeViewDebug::emitDebugInfoForFunction(const Function *GV,
// If we have a display name, build the fully qualified name by walking the
// chain of scopes.
if (!SP->getName().empty())
- FuncName =
- getFullyQualifiedName(SP->getScope().resolve(), SP->getName());
+ FuncName = getFullyQualifiedName(SP->getScope(), SP->getName());
// If our DISubprogram name is empty, use the mangled name.
if (FuncName.empty())
@@ -1071,6 +1126,28 @@ void CodeViewDebug::emitDebugInfoForFunction(const Function *GV,
endSymbolRecord(AnnotEnd);
}
+ for (auto HeapAllocSite : FI.HeapAllocSites) {
+ MCSymbol *BeginLabel = std::get<0>(HeapAllocSite);
+ MCSymbol *EndLabel = std::get<1>(HeapAllocSite);
+
+ // The labels might not be defined if the instruction was replaced
+ // somewhere in the codegen pipeline.
+ if (!BeginLabel->isDefined() || !EndLabel->isDefined())
+ continue;
+
+ DIType *DITy = std::get<2>(HeapAllocSite);
+ MCSymbol *HeapAllocEnd = beginSymbolRecord(SymbolKind::S_HEAPALLOCSITE);
+ OS.AddComment("Call site offset");
+ OS.EmitCOFFSecRel32(BeginLabel, /*Offset=*/0);
+ OS.AddComment("Call site section index");
+ OS.EmitCOFFSectionIndex(BeginLabel);
+ OS.AddComment("Call instruction length");
+ OS.emitAbsoluteSymbolDiff(EndLabel, BeginLabel, 2);
+ OS.AddComment("Type index");
+ OS.EmitIntValue(getCompleteTypeIndex(DITy).getIndex(), 4);
+ endSymbolRecord(HeapAllocEnd);
+ }
+
if (SP != nullptr)
emitDebugInfoForUDTs(LocalUDTs);
@@ -1118,9 +1195,15 @@ void CodeViewDebug::collectVariableInfoFromMFTable(
// If the variable has an attached offset expression, extract it.
// FIXME: Try to handle DW_OP_deref as well.
int64_t ExprOffset = 0;
- if (VI.Expr)
- if (!VI.Expr->extractIfOffset(ExprOffset))
+ bool Deref = false;
+ if (VI.Expr) {
+ // If there is one DW_OP_deref element, use offset of 0 and keep going.
+ if (VI.Expr->getNumElements() == 1 &&
+ VI.Expr->getElement(0) == llvm::dwarf::DW_OP_deref)
+ Deref = true;
+ else if (!VI.Expr->extractIfOffset(ExprOffset))
continue;
+ }
// Get the frame register used and the offset.
unsigned FrameReg = 0;
@@ -1130,6 +1213,7 @@ void CodeViewDebug::collectVariableInfoFromMFTable(
// Calculate the label ranges.
LocalVarDefRange DefRange =
createDefRangeMem(CVReg, FrameOffset + ExprOffset);
+
for (const InsnRange &Range : Scope->getRanges()) {
const MCSymbol *Begin = getLabelBeforeInsn(Range.first);
const MCSymbol *End = getLabelAfterInsn(Range.second);
@@ -1140,6 +1224,9 @@ void CodeViewDebug::collectVariableInfoFromMFTable(
LocalVariable Var;
Var.DIVar = VI.Var;
Var.DefRanges.emplace_back(std::move(DefRange));
+ if (Deref)
+ Var.UseReferenceType = true;
+
recordLocalVariable(std::move(Var), Scope);
}
}
@@ -1153,13 +1240,15 @@ static bool needsReferenceType(const DbgVariableLocation &Loc) {
}
void CodeViewDebug::calculateRanges(
- LocalVariable &Var, const DbgValueHistoryMap::InstrRanges &Ranges) {
+ LocalVariable &Var, const DbgValueHistoryMap::Entries &Entries) {
const TargetRegisterInfo *TRI = Asm->MF->getSubtarget().getRegisterInfo();
// Calculate the definition ranges.
- for (auto I = Ranges.begin(), E = Ranges.end(); I != E; ++I) {
- const InsnRange &Range = *I;
- const MachineInstr *DVInst = Range.first;
+ for (auto I = Entries.begin(), E = Entries.end(); I != E; ++I) {
+ const auto &Entry = *I;
+ if (!Entry.isDbgValue())
+ continue;
+ const MachineInstr *DVInst = Entry.getInstr();
assert(DVInst->isDebugValue() && "Invalid History entry");
// FIXME: Find a way to represent constant variables, since they are
// relatively common.
@@ -1186,7 +1275,7 @@ void CodeViewDebug::calculateRanges(
// Start over using that.
Var.UseReferenceType = true;
Var.DefRanges.clear();
- calculateRanges(Var, Ranges);
+ calculateRanges(Var, Entries);
return;
}
@@ -1214,21 +1303,15 @@ void CodeViewDebug::calculateRanges(
}
// Compute the label range.
- const MCSymbol *Begin = getLabelBeforeInsn(Range.first);
- const MCSymbol *End = getLabelAfterInsn(Range.second);
- if (!End) {
- // This range is valid until the next overlapping bitpiece. In the
- // common case, ranges will not be bitpieces, so they will overlap.
- auto J = std::next(I);
- const DIExpression *DIExpr = DVInst->getDebugExpression();
- while (J != E &&
- !DIExpr->fragmentsOverlap(J->first->getDebugExpression()))
- ++J;
- if (J != E)
- End = getLabelBeforeInsn(J->first);
- else
- End = Asm->getFunctionEnd();
- }
+ const MCSymbol *Begin = getLabelBeforeInsn(Entry.getInstr());
+ const MCSymbol *End;
+ if (Entry.getEndIndex() != DbgValueHistoryMap::NoEntry) {
+ auto &EndingEntry = Entries[Entry.getEndIndex()];
+ End = EndingEntry.isDbgValue()
+ ? getLabelBeforeInsn(EndingEntry.getInstr())
+ : getLabelAfterInsn(EndingEntry.getInstr());
+ } else
+ End = Asm->getFunctionEnd();
// If the last range end is our begin, just extend the last range.
// Otherwise make a new range.
@@ -1256,7 +1339,7 @@ void CodeViewDebug::collectVariableInfo(const DISubprogram *SP) {
const DILocation *InlinedAt = IV.second;
// Instruction ranges, specifying where IV is accessible.
- const auto &Ranges = I.second;
+ const auto &Entries = I.second;
LexicalScope *Scope = nullptr;
if (InlinedAt)
@@ -1270,7 +1353,7 @@ void CodeViewDebug::collectVariableInfo(const DISubprogram *SP) {
LocalVariable Var;
Var.DIVar = DIVar;
- calculateRanges(Var, Ranges);
+ calculateRanges(Var, Entries);
recordLocalVariable(std::move(Var), Scope);
}
}
@@ -1340,8 +1423,8 @@ void CodeViewDebug::beginFunctionImpl(const MachineFunction *MF) {
FPO |= FrameProcedureOptions::SecurityChecks;
FPO |= FrameProcedureOptions(uint32_t(CurFn->EncodedLocalFramePtrReg) << 14U);
FPO |= FrameProcedureOptions(uint32_t(CurFn->EncodedParamFramePtrReg) << 16U);
- if (Asm->TM.getOptLevel() != CodeGenOpt::None && !GV.optForSize() &&
- !GV.hasFnAttribute(Attribute::OptimizeNone))
+ if (Asm->TM.getOptLevel() != CodeGenOpt::None &&
+ !GV.hasOptSize() && !GV.hasOptNone())
FPO |= FrameProcedureOptions::OptimizedForSpeed;
// FIXME: Set GuardCfg when it is implemented.
CurFn->FrameProcOpts = FPO;
@@ -1379,7 +1462,7 @@ static bool shouldEmitUdt(const DIType *T) {
// MSVC does not emit UDTs for typedefs that are scoped to classes.
if (T->getTag() == dwarf::DW_TAG_typedef) {
- if (DIScope *Scope = T->getScope().resolve()) {
+ if (DIScope *Scope = T->getScope()) {
switch (Scope->getTag()) {
case dwarf::DW_TAG_structure_type:
case dwarf::DW_TAG_class_type:
@@ -1396,7 +1479,7 @@ static bool shouldEmitUdt(const DIType *T) {
const DIDerivedType *DT = dyn_cast<DIDerivedType>(T);
if (!DT)
return true;
- T = DT->getBaseType().resolve();
+ T = DT->getBaseType();
}
return true;
}
@@ -1409,8 +1492,8 @@ void CodeViewDebug::addToUDTs(const DIType *Ty) {
return;
SmallVector<StringRef, 5> QualifiedNameComponents;
- const DISubprogram *ClosestSubprogram = getQualifiedNameComponents(
- Ty->getScope().resolve(), QualifiedNameComponents);
+ const DISubprogram *ClosestSubprogram =
+ getQualifiedNameComponents(Ty->getScope(), QualifiedNameComponents);
std::string FullyQualifiedName =
getQualifiedName(QualifiedNameComponents, getPrettyScopeName(Ty));
@@ -1479,8 +1562,7 @@ TypeIndex CodeViewDebug::lowerType(const DIType *Ty, const DIType *ClassTy) {
}
TypeIndex CodeViewDebug::lowerTypeAlias(const DIDerivedType *Ty) {
- DITypeRef UnderlyingTypeRef = Ty->getBaseType();
- TypeIndex UnderlyingTypeIndex = getTypeIndex(UnderlyingTypeRef);
+ TypeIndex UnderlyingTypeIndex = getTypeIndex(Ty->getBaseType());
StringRef TypeName = Ty->getName();
addToUDTs(Ty);
@@ -1496,14 +1578,14 @@ TypeIndex CodeViewDebug::lowerTypeAlias(const DIDerivedType *Ty) {
}
TypeIndex CodeViewDebug::lowerTypeArray(const DICompositeType *Ty) {
- DITypeRef ElementTypeRef = Ty->getBaseType();
- TypeIndex ElementTypeIndex = getTypeIndex(ElementTypeRef);
+ const DIType *ElementType = Ty->getBaseType();
+ TypeIndex ElementTypeIndex = getTypeIndex(ElementType);
// IndexType is size_t, which depends on the bitness of the target.
TypeIndex IndexType = getPointerSizeInBytes() == 8
? TypeIndex(SimpleTypeKind::UInt64Quad)
: TypeIndex(SimpleTypeKind::UInt32Long);
- uint64_t ElementSize = getBaseTypeSize(ElementTypeRef) / 8;
+ uint64_t ElementSize = getBaseTypeSize(ElementType) / 8;
// Add subranges to array type.
DINodeArray Elements = Ty->getElements();
@@ -1764,7 +1846,7 @@ TypeIndex CodeViewDebug::lowerTypeModifier(const DIDerivedType *Ty) {
break;
}
if (IsModifier)
- BaseTy = cast<DIDerivedType>(BaseTy)->getBaseType().resolve();
+ BaseTy = cast<DIDerivedType>(BaseTy)->getBaseType();
}
// Check if the inner type will use an LF_POINTER record. If so, the
@@ -1797,8 +1879,8 @@ TypeIndex CodeViewDebug::lowerTypeModifier(const DIDerivedType *Ty) {
TypeIndex CodeViewDebug::lowerTypeFunction(const DISubroutineType *Ty) {
SmallVector<TypeIndex, 8> ReturnAndArgTypeIndices;
- for (DITypeRef ArgTypeRef : Ty->getTypeArray())
- ReturnAndArgTypeIndices.push_back(getTypeIndex(ArgTypeRef));
+ for (const DIType *ArgType : Ty->getTypeArray())
+ ReturnAndArgTypeIndices.push_back(getTypeIndex(ArgType));
// MSVC uses type none for variadic argument.
if (ReturnAndArgTypeIndices.size() > 1 &&
@@ -1836,7 +1918,10 @@ TypeIndex CodeViewDebug::lowerTypeMemberFunction(const DISubroutineType *Ty,
unsigned Index = 0;
SmallVector<TypeIndex, 8> ArgTypeIndices;
- TypeIndex ReturnTypeIndex = getTypeIndex(ReturnAndArgs[Index++]);
+ TypeIndex ReturnTypeIndex = TypeIndex::Void();
+ if (ReturnAndArgs.size() > Index) {
+ ReturnTypeIndex = getTypeIndex(ReturnAndArgs[Index++]);
+ }
// If the first argument is a pointer type and this isn't a static method,
// treat it as the special 'this' parameter, which is encoded separately from
@@ -1844,7 +1929,7 @@ TypeIndex CodeViewDebug::lowerTypeMemberFunction(const DISubroutineType *Ty,
TypeIndex ThisTypeIndex;
if (!IsStaticMethod && ReturnAndArgs.size() > Index) {
if (const DIDerivedType *PtrTy =
- dyn_cast_or_null<DIDerivedType>(ReturnAndArgs[Index].resolve())) {
+ dyn_cast_or_null<DIDerivedType>(ReturnAndArgs[Index])) {
if (PtrTy->getTag() == dwarf::DW_TAG_pointer_type) {
ThisTypeIndex = getTypeIndexForThisPtr(PtrTy, Ty);
Index++;
@@ -1942,7 +2027,7 @@ static ClassOptions getCommonClassOptions(const DICompositeType *Ty) {
// Put the Nested flag on a type if it appears immediately inside a tag type.
// Do not walk the scope chain. Do not attempt to compute ContainsNestedClass
// here. That flag is only set on definitions, and not forward declarations.
- const DIScope *ImmediateScope = Ty->getScope().resolve();
+ const DIScope *ImmediateScope = Ty->getScope();
if (ImmediateScope && isa<DICompositeType>(ImmediateScope))
CO |= ClassOptions::Nested;
@@ -1955,7 +2040,7 @@ static ClassOptions getCommonClassOptions(const DICompositeType *Ty) {
CO |= ClassOptions::Scoped;
} else {
for (const DIScope *Scope = ImmediateScope; Scope != nullptr;
- Scope = Scope->getScope().resolve()) {
+ Scope = Scope->getScope()) {
if (isa<DISubprogram>(Scope)) {
CO |= ClassOptions::Scoped;
break;
@@ -2075,7 +2160,7 @@ void CodeViewDebug::collectMemberInfo(ClassInfo &Info,
// 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 DIType *Ty = DDTy->getBaseType();
bool FullyResolved = false;
while (!FullyResolved) {
switch (Ty->getTag()) {
@@ -2083,7 +2168,7 @@ void CodeViewDebug::collectMemberInfo(ClassInfo &Info,
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();
+ Ty = cast<DIDerivedType>(Ty)->getBaseType();
break;
default:
FullyResolved = true;
@@ -2184,6 +2269,14 @@ TypeIndex CodeViewDebug::lowerCompleteTypeClass(const DICompositeType *Ty) {
if (ContainsNestedClass)
CO |= ClassOptions::ContainsNestedClass;
+ // MSVC appears to set this flag by searching any destructor or method with
+ // FunctionOptions::Constructor among the emitted members. Clang AST has all
+ // the members, however special member functions are not yet emitted into
+ // debug information. For now checking a class's non-triviality seems enough.
+ // FIXME: not true for a nested unnamed struct.
+ if (isNonTrivial(Ty))
+ CO |= ClassOptions::HasConstructorOrDestructor;
+
std::string FullName = getFullyQualifiedName(Ty);
uint64_t SizeInBytes = Ty->getSizeInBits() / 8;
@@ -2358,7 +2451,7 @@ CodeViewDebug::lowerRecordFieldList(const DICompositeType *Ty) {
// Create nested classes.
for (const DIType *Nested : Info.NestedTypes) {
- NestedTypeRecord R(getTypeIndex(DITypeRef(Nested)), Nested->getName());
+ NestedTypeRecord R(getTypeIndex(Nested), Nested->getName());
ContinuationBuilder.writeMemberType(R);
MemberCount++;
}
@@ -2385,10 +2478,7 @@ TypeIndex CodeViewDebug::getVBPTypeIndex() {
return VBPType;
}
-TypeIndex CodeViewDebug::getTypeIndex(DITypeRef TypeRef, DITypeRef ClassTyRef) {
- const DIType *Ty = TypeRef.resolve();
- const DIType *ClassTy = ClassTyRef.resolve();
-
+TypeIndex CodeViewDebug::getTypeIndex(const DIType *Ty, const DIType *ClassTy) {
// The null DIType is the void type. Don't try to hash it.
if (!Ty)
return TypeIndex::Void();
@@ -2431,8 +2521,7 @@ CodeViewDebug::getTypeIndexForThisPtr(const DIDerivedType *PtrTy,
return recordTypeIndexForDINode(PtrTy, TI, SubroutineTy);
}
-TypeIndex CodeViewDebug::getTypeIndexForReferenceTo(DITypeRef TypeRef) {
- DIType *Ty = TypeRef.resolve();
+TypeIndex CodeViewDebug::getTypeIndexForReferenceTo(const DIType *Ty) {
PointerRecord PR(getTypeIndex(Ty),
getPointerSizeInBytes() == 8 ? PointerKind::Near64
: PointerKind::Near32,
@@ -2441,9 +2530,7 @@ TypeIndex CodeViewDebug::getTypeIndexForReferenceTo(DITypeRef TypeRef) {
return TypeTable.writeLeafType(PR);
}
-TypeIndex CodeViewDebug::getCompleteTypeIndex(DITypeRef TypeRef) {
- const DIType *Ty = TypeRef.resolve();
-
+TypeIndex CodeViewDebug::getCompleteTypeIndex(const DIType *Ty) {
// The null DIType is the void type. Don't try to hash it.
if (!Ty)
return TypeIndex::Void();
@@ -2454,7 +2541,7 @@ TypeIndex CodeViewDebug::getCompleteTypeIndex(DITypeRef TypeRef) {
if (Ty->getTag() == dwarf::DW_TAG_typedef)
(void)getTypeIndex(Ty);
while (Ty->getTag() == dwarf::DW_TAG_typedef)
- Ty = cast<DIDerivedType>(Ty)->getBaseType().resolve();
+ Ty = cast<DIDerivedType>(Ty)->getBaseType();
// If this is a non-record type, the complete type index is the same as the
// normal type index. Just call getTypeIndex.
@@ -2467,11 +2554,7 @@ TypeIndex CodeViewDebug::getCompleteTypeIndex(DITypeRef TypeRef) {
return getTypeIndex(Ty);
}
- // 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)
- return InsertResult.first->second;
TypeLoweringScope S(*this);
@@ -2489,6 +2572,13 @@ TypeIndex CodeViewDebug::getCompleteTypeIndex(DITypeRef TypeRef) {
return FwdDeclTI;
}
+ // Check if we've already translated the complete record type.
+ // Insert the type with a null TypeIndex to signify that the type is currently
+ // being lowered.
+ auto InsertResult = CompleteTypeIndices.insert({CTy, TypeIndex()});
+ if (!InsertResult.second)
+ return InsertResult.first->second;
+
TypeIndex TI;
switch (CTy->getTag()) {
case dwarf::DW_TAG_class_type:
@@ -2799,6 +2889,7 @@ void CodeViewDebug::endFunctionImpl(const MachineFunction *MF) {
}
CurFn->Annotations = MF->getCodeViewAnnotations();
+ CurFn->HeapAllocSites = MF->getCodeViewHeapAllocSites();
CurFn->End = Asm->getFunctionEnd();
@@ -2914,10 +3005,19 @@ void CodeViewDebug::collectGlobalVariableInfo() {
for (const MDNode *Node : CUs->operands()) {
const auto *CU = cast<DICompileUnit>(Node);
for (const auto *GVE : CU->getGlobalVariables()) {
+ const DIGlobalVariable *DIGV = GVE->getVariable();
+ const DIExpression *DIE = GVE->getExpression();
+
+ // Emit constant global variables in a global symbol section.
+ if (GlobalMap.count(GVE) == 0 && DIE->isConstant()) {
+ CVGlobalVariable CVGV = {DIGV, DIE};
+ GlobalVariables.emplace_back(std::move(CVGV));
+ }
+
const auto *GV = GlobalMap.lookup(GVE);
if (!GV || GV->isDeclarationForLinker())
continue;
- const DIGlobalVariable *DIGV = GVE->getVariable();
+
DIScope *Scope = DIGV->getScope();
SmallVector<CVGlobalVariable, 1> *VariableList;
if (Scope && isa<DILocalScope>(Scope)) {
@@ -2932,7 +3032,7 @@ void CodeViewDebug::collectGlobalVariableInfo() {
// Emit this global variable into a COMDAT section.
VariableList = &ComdatVariables;
else
- // Emit this globla variable in a single global symbol section.
+ // Emit this global variable in a single global symbol section.
VariableList = &GlobalVariables;
CVGlobalVariable CVGV = {DIGV, GV};
VariableList->emplace_back(std::move(CVGV));
@@ -2955,13 +3055,14 @@ void CodeViewDebug::emitDebugInfoForGlobals() {
// Second, emit each global that is in a comdat into its own .debug$S
// section along with its own symbol substream.
for (const CVGlobalVariable &CVGV : ComdatVariables) {
- MCSymbol *GVSym = Asm->getSymbol(CVGV.GV);
+ const GlobalVariable *GV = CVGV.GVInfo.get<const GlobalVariable *>();
+ MCSymbol *GVSym = Asm->getSymbol(GV);
OS.AddComment("Symbol subsection for " +
- Twine(GlobalValue::dropLLVMManglingEscape(CVGV.GV->getName())));
+ Twine(GlobalValue::dropLLVMManglingEscape(GV->getName())));
switchToDebugSectionForSymbol(GVSym);
MCSymbol *EndLabel = beginCVSubsection(DebugSubsectionKind::Symbols);
// FIXME: emitDebugInfoForGlobal() doesn't handle DIExpressions.
- emitDebugInfoForGlobal(CVGV.DIGV, CVGV.GV, GVSym);
+ emitDebugInfoForGlobal(CVGV);
endCVSubsection(EndLabel);
}
}
@@ -2981,31 +3082,63 @@ void CodeViewDebug::emitDebugInfoForRetainedTypes() {
// Emit each global variable in the specified array.
void CodeViewDebug::emitGlobalVariableList(ArrayRef<CVGlobalVariable> Globals) {
for (const CVGlobalVariable &CVGV : Globals) {
- MCSymbol *GVSym = Asm->getSymbol(CVGV.GV);
// FIXME: emitDebugInfoForGlobal() doesn't handle DIExpressions.
- emitDebugInfoForGlobal(CVGV.DIGV, CVGV.GV, GVSym);
- }
-}
-
-void CodeViewDebug::emitDebugInfoForGlobal(const DIGlobalVariable *DIGV,
- const GlobalVariable *GV,
- MCSymbol *GVSym) {
- // DataSym record, see SymbolRecord.h for more info. Thread local data
- // happens to have the same format as global data.
- SymbolKind DataSym = GV->isThreadLocal()
- ? (DIGV->isLocalToUnit() ? SymbolKind::S_LTHREAD32
- : SymbolKind::S_GTHREAD32)
- : (DIGV->isLocalToUnit() ? SymbolKind::S_LDATA32
- : SymbolKind::S_GDATA32);
- MCSymbol *DataEnd = beginSymbolRecord(DataSym);
- OS.AddComment("Type");
- OS.EmitIntValue(getCompleteTypeIndex(DIGV->getType()).getIndex(), 4);
- OS.AddComment("DataOffset");
- OS.EmitCOFFSecRel32(GVSym, /*Offset=*/0);
- OS.AddComment("Segment");
- OS.EmitCOFFSectionIndex(GVSym);
- OS.AddComment("Name");
- const unsigned LengthOfDataRecord = 12;
- emitNullTerminatedSymbolName(OS, DIGV->getName(), LengthOfDataRecord);
- endSymbolRecord(DataEnd);
+ emitDebugInfoForGlobal(CVGV);
+ }
+}
+
+void CodeViewDebug::emitDebugInfoForGlobal(const CVGlobalVariable &CVGV) {
+ const DIGlobalVariable *DIGV = CVGV.DIGV;
+ if (const GlobalVariable *GV =
+ CVGV.GVInfo.dyn_cast<const GlobalVariable *>()) {
+ // DataSym record, see SymbolRecord.h for more info. Thread local data
+ // happens to have the same format as global data.
+ MCSymbol *GVSym = Asm->getSymbol(GV);
+ SymbolKind DataSym = GV->isThreadLocal()
+ ? (DIGV->isLocalToUnit() ? SymbolKind::S_LTHREAD32
+ : SymbolKind::S_GTHREAD32)
+ : (DIGV->isLocalToUnit() ? SymbolKind::S_LDATA32
+ : SymbolKind::S_GDATA32);
+ MCSymbol *DataEnd = beginSymbolRecord(DataSym);
+ OS.AddComment("Type");
+ OS.EmitIntValue(getCompleteTypeIndex(DIGV->getType()).getIndex(), 4);
+ OS.AddComment("DataOffset");
+ OS.EmitCOFFSecRel32(GVSym, /*Offset=*/0);
+ OS.AddComment("Segment");
+ OS.EmitCOFFSectionIndex(GVSym);
+ OS.AddComment("Name");
+ const unsigned LengthOfDataRecord = 12;
+ emitNullTerminatedSymbolName(OS, DIGV->getName(), LengthOfDataRecord);
+ endSymbolRecord(DataEnd);
+ } else {
+ // FIXME: Currently this only emits the global variables in the IR metadata.
+ // This should also emit enums and static data members.
+ const DIExpression *DIE = CVGV.GVInfo.get<const DIExpression *>();
+ assert(DIE->isConstant() &&
+ "Global constant variables must contain a constant expression.");
+ uint64_t Val = DIE->getElement(1);
+
+ MCSymbol *SConstantEnd = beginSymbolRecord(SymbolKind::S_CONSTANT);
+ OS.AddComment("Type");
+ OS.EmitIntValue(getTypeIndex(DIGV->getType()).getIndex(), 4);
+ OS.AddComment("Value");
+
+ // Encoded integers shouldn't need more than 10 bytes.
+ uint8_t data[10];
+ BinaryStreamWriter Writer(data, llvm::support::endianness::little);
+ CodeViewRecordIO IO(Writer);
+ cantFail(IO.mapEncodedInteger(Val));
+ StringRef SRef((char *)data, Writer.getOffset());
+ OS.EmitBinaryData(SRef);
+
+ OS.AddComment("Name");
+ const DIScope *Scope = DIGV->getScope();
+ // For static data members, get the scope from the declaration.
+ if (const auto *MemberDecl = dyn_cast_or_null<DIDerivedType>(
+ DIGV->getRawStaticDataMemberDeclaration()))
+ Scope = MemberDecl->getScope();
+ emitNullTerminatedSymbolName(OS,
+ getFullyQualifiedName(Scope, DIGV->getName()));
+ endSymbolRecord(SConstantEnd);
+ }
}
diff --git a/lib/CodeGen/AsmPrinter/CodeViewDebug.h b/lib/CodeGen/AsmPrinter/CodeViewDebug.h
index 21557ed1be35..ce57b789d7fa 100644
--- a/lib/CodeGen/AsmPrinter/CodeViewDebug.h
+++ b/lib/CodeGen/AsmPrinter/CodeViewDebug.h
@@ -1,9 +1,8 @@
//===- llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h --------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -18,6 +17,7 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/MapVector.h"
+#include "llvm/ADT/PointerUnion.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/CodeGen/DbgEntityHistoryCalculator.h"
@@ -101,7 +101,7 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDebug : public DebugHandlerBase {
struct CVGlobalVariable {
const DIGlobalVariable *DIGV;
- const GlobalVariable *GV;
+ PointerUnion<const GlobalVariable *, const DIExpression *> GVInfo;
};
struct InlineSite {
@@ -148,6 +148,7 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDebug : public DebugHandlerBase {
SmallVector<LexicalBlock *, 1> ChildBlocks;
std::vector<std::pair<MCSymbol *, MDNode *>> Annotations;
+ std::vector<std::tuple<MCSymbol *, MCSymbol *, DIType *>> HeapAllocSites;
const MCSymbol *Begin = nullptr;
const MCSymbol *End = nullptr;
@@ -223,7 +224,7 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDebug : public DebugHandlerBase {
codeview::TypeIndex getFuncIdForSubprogram(const DISubprogram *SP);
void calculateRanges(LocalVariable &Var,
- const DbgValueHistoryMap::InstrRanges &Ranges);
+ const DbgValueHistoryMap::Entries &Entries);
static void collectInlineSiteChildren(SmallVectorImpl<unsigned> &Children,
const FunctionInfo &FI,
@@ -313,8 +314,7 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDebug : public DebugHandlerBase {
void emitDebugInfoForGlobals();
void emitGlobalVariableList(ArrayRef<CVGlobalVariable> Globals);
- void emitDebugInfoForGlobal(const DIGlobalVariable *DIGV,
- const GlobalVariable *GV, MCSymbol *GVSym);
+ void emitDebugInfoForGlobal(const CVGlobalVariable &CVGV);
/// Opens a subsection of the given kind in a .debug$S codeview section.
/// Returns an end label for use with endCVSubsection when the subsection is
@@ -373,14 +373,14 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDebug : public DebugHandlerBase {
/// Translates the DIType to codeview if necessary and returns a type index
/// for it.
- codeview::TypeIndex getTypeIndex(DITypeRef TypeRef,
- DITypeRef ClassTyRef = DITypeRef());
+ codeview::TypeIndex getTypeIndex(const DIType *Ty,
+ const DIType *ClassTy = nullptr);
codeview::TypeIndex
getTypeIndexForThisPtr(const DIDerivedType *PtrTy,
const DISubroutineType *SubroutineTy);
- codeview::TypeIndex getTypeIndexForReferenceTo(DITypeRef TypeRef);
+ codeview::TypeIndex getTypeIndexForReferenceTo(const DIType *Ty);
codeview::TypeIndex getMemberFunctionType(const DISubprogram *SP,
const DICompositeType *Class);
@@ -419,7 +419,7 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDebug : public DebugHandlerBase {
/// use this entry point when generating symbol records. The complete and
/// incomplete type indices only differ for record types. All other types use
/// the same index.
- codeview::TypeIndex getCompleteTypeIndex(DITypeRef TypeRef);
+ codeview::TypeIndex getCompleteTypeIndex(const DIType *Ty);
codeview::TypeIndex lowerCompleteTypeClass(const DICompositeType *Ty);
codeview::TypeIndex lowerCompleteTypeUnion(const DICompositeType *Ty);
diff --git a/lib/CodeGen/AsmPrinter/DIE.cpp b/lib/CodeGen/AsmPrinter/DIE.cpp
index e27659494f08..f4134da48caa 100644
--- a/lib/CodeGen/AsmPrinter/DIE.cpp
+++ b/lib/CodeGen/AsmPrinter/DIE.cpp
@@ -1,9 +1,8 @@
//===--- lib/CodeGen/DIE.cpp - DWARF Info Entries -------------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -212,7 +211,7 @@ const DIE *DIE::getUnitDie() const {
return nullptr;
}
-const DIEUnit *DIE::getUnit() const {
+DIEUnit *DIE::getUnit() const {
const DIE *UnitDie = getUnitDie();
if (UnitDie)
return UnitDie->Owner.dyn_cast<DIEUnit*>();
@@ -507,6 +506,23 @@ LLVM_DUMP_METHOD
void DIELabel::print(raw_ostream &O) const { O << "Lbl: " << Label->getName(); }
//===----------------------------------------------------------------------===//
+// DIEBaseTypeRef Implementation
+//===----------------------------------------------------------------------===//
+
+void DIEBaseTypeRef::EmitValue(const AsmPrinter *AP, dwarf::Form Form) const {
+ uint64_t Offset = CU->ExprRefedBaseTypes[Index].Die->getOffset();
+ assert(Offset < (1ULL << (ULEB128PadSize * 7)) && "Offset wont fit");
+ AP->EmitULEB128(Offset, nullptr, ULEB128PadSize);
+}
+
+unsigned DIEBaseTypeRef::SizeOf(const AsmPrinter *AP, dwarf::Form Form) const {
+ return ULEB128PadSize;
+}
+
+LLVM_DUMP_METHOD
+void DIEBaseTypeRef::print(raw_ostream &O) const { O << "BaseTypeRef: " << Index; }
+
+//===----------------------------------------------------------------------===//
// DIEDelta Implementation
//===----------------------------------------------------------------------===//
diff --git a/lib/CodeGen/AsmPrinter/DIEHash.cpp b/lib/CodeGen/AsmPrinter/DIEHash.cpp
index b8f1202494d7..bfac8850a2a6 100644
--- a/lib/CodeGen/AsmPrinter/DIEHash.cpp
+++ b/lib/CodeGen/AsmPrinter/DIEHash.cpp
@@ -1,9 +1,8 @@
//===-- llvm/CodeGen/DIEHash.cpp - Dwarf Hashing Framework ----------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -226,7 +225,7 @@ void DIEHash::hashLocList(const DIELocList &LocList) {
DwarfDebug &DD = *AP->getDwarfDebug();
const DebugLocStream &Locs = DD.getDebugLocs();
for (const auto &Entry : Locs.getEntries(Locs.getList(LocList.getValue())))
- DD.emitDebugLocEntry(Streamer, Entry);
+ DD.emitDebugLocEntry(Streamer, Entry, nullptr);
}
// Hash an individual attribute \param Attr based on the type of attribute and
@@ -310,6 +309,7 @@ void DIEHash::hashAttribute(const DIEValue &Value, dwarf::Tag Tag) {
// FIXME: It's uncertain whether or not we should handle this at the moment.
case DIEValue::isExpr:
case DIEValue::isLabel:
+ case DIEValue::isBaseTypeRef:
case DIEValue::isDelta:
llvm_unreachable("Add support for additional value types.");
}
diff --git a/lib/CodeGen/AsmPrinter/DIEHash.h b/lib/CodeGen/AsmPrinter/DIEHash.h
index dae517ab2c29..2e49514c98be 100644
--- a/lib/CodeGen/AsmPrinter/DIEHash.h
+++ b/lib/CodeGen/AsmPrinter/DIEHash.h
@@ -1,9 +1,8 @@
//===-- llvm/CodeGen/DIEHash.h - Dwarf Hashing Framework -------*- C++ -*--===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
diff --git a/lib/CodeGen/AsmPrinter/DbgEntityHistoryCalculator.cpp b/lib/CodeGen/AsmPrinter/DbgEntityHistoryCalculator.cpp
index 09867822c30a..ddd60575b6c0 100644
--- a/lib/CodeGen/AsmPrinter/DbgEntityHistoryCalculator.cpp
+++ b/lib/CodeGen/AsmPrinter/DbgEntityHistoryCalculator.cpp
@@ -1,15 +1,15 @@
//===- llvm/CodeGen/AsmPrinter/DbgEntityHistoryCalculator.cpp -------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "llvm/CodeGen/DbgEntityHistoryCalculator.h"
#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineFunction.h"
@@ -31,51 +31,62 @@ using namespace llvm;
#define DEBUG_TYPE "dwarfdebug"
+namespace {
+using EntryIndex = DbgValueHistoryMap::EntryIndex;
+}
+
// 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) {
+static Register isDescribedByReg(const MachineInstr &MI) {
assert(MI.isDebugValue());
assert(MI.getNumOperands() == 4);
+ // If the location of variable is an entry value (DW_OP_entry_value)
+ // do not consider it as a register location.
+ if (MI.getDebugExpression()->isEntryValue())
+ return 0;
// If location of variable is described using a register (directly or
// indirectly), this register is always a first operand.
- return MI.getOperand(0).isReg() ? MI.getOperand(0).getReg() : 0;
+ return MI.getOperand(0).isReg() ? MI.getOperand(0).getReg() : Register();
}
-void DbgValueHistoryMap::startInstrRange(InlinedEntity Var,
- const MachineInstr &MI) {
+bool DbgValueHistoryMap::startDbgValue(InlinedEntity Var,
+ const MachineInstr &MI,
+ EntryIndex &NewIndex) {
// Instruction range should start with a DBG_VALUE instruction for the
// variable.
assert(MI.isDebugValue() && "not a DBG_VALUE");
- auto &Ranges = VarInstrRanges[Var];
- if (!Ranges.empty() && Ranges.back().second == nullptr &&
- Ranges.back().first->isIdenticalTo(MI)) {
+ auto &Entries = VarEntries[Var];
+ if (!Entries.empty() && Entries.back().isDbgValue() &&
+ !Entries.back().isClosed() &&
+ Entries.back().getInstr()->isIdenticalTo(MI)) {
LLVM_DEBUG(dbgs() << "Coalescing identical DBG_VALUE entries:\n"
- << "\t" << Ranges.back().first << "\t" << MI << "\n");
- return;
+ << "\t" << Entries.back().getInstr() << "\t" << MI
+ << "\n");
+ return false;
}
- Ranges.push_back(std::make_pair(&MI, nullptr));
+ Entries.emplace_back(&MI, Entry::DbgValue);
+ NewIndex = Entries.size() - 1;
+ return true;
}
-void DbgValueHistoryMap::endInstrRange(InlinedEntity Var,
- const MachineInstr &MI) {
- auto &Ranges = VarInstrRanges[Var];
- // Verify that the current instruction range is not yet closed.
- assert(!Ranges.empty() && Ranges.back().second == nullptr);
- // For now, instruction ranges are not allowed to cross basic block
- // boundaries.
- assert(Ranges.back().first->getParent() == MI.getParent());
- Ranges.back().second = &MI;
+EntryIndex DbgValueHistoryMap::startClobber(InlinedEntity Var,
+ const MachineInstr &MI) {
+ auto &Entries = VarEntries[Var];
+ // If an instruction clobbers multiple registers that the variable is
+ // described by, then we may have already created a clobbering instruction.
+ if (Entries.back().isClobber() && Entries.back().getInstr() == &MI)
+ return Entries.size() - 1;
+ Entries.emplace_back(&MI, Entry::Clobber);
+ return Entries.size() - 1;
}
-unsigned DbgValueHistoryMap::getRegisterForVar(InlinedEntity Var) const {
- const auto &I = VarInstrRanges.find(Var);
- if (I == VarInstrRanges.end())
- return 0;
- const auto &Ranges = I->second;
- if (Ranges.empty() || Ranges.back().second != nullptr)
- return 0;
- return isDescribedByReg(*Ranges.back().first);
+void DbgValueHistoryMap::Entry::endEntry(EntryIndex Index) {
+ // For now, instruction ranges are not allowed to cross basic block
+ // boundaries.
+ assert(isDbgValue() && "Setting end index for non-debug value");
+ assert(!isClosed() && "End index has already been set");
+ EndIndex = Index;
}
void DbgLabelInstrMap::addInstr(InlinedEntity Label, const MachineInstr &MI) {
@@ -89,6 +100,12 @@ namespace {
using InlinedEntity = DbgValueHistoryMap::InlinedEntity;
using RegDescribedVarsMap = std::map<unsigned, SmallVector<InlinedEntity, 1>>;
+// Keeps track of the debug value entries that are currently live for each
+// inlined entity. As the history map entries are stored in a SmallVector, they
+// may be moved at insertion of new entries, so store indices rather than
+// pointers.
+using DbgValueEntriesMap = std::map<InlinedEntity, SmallSet<EntryIndex, 1>>;
+
} // end anonymous namespace
// Claim that @Var is not described by @RegNo anymore.
@@ -114,16 +131,88 @@ static void addRegDescribedVar(RegDescribedVarsMap &RegVars, unsigned RegNo,
VarSet.push_back(Var);
}
+/// Create a clobbering entry and end all open debug value entries
+/// for \p Var that are described by \p RegNo using that entry.
+static void clobberRegEntries(InlinedEntity Var, unsigned RegNo,
+ const MachineInstr &ClobberingInstr,
+ DbgValueEntriesMap &LiveEntries,
+ DbgValueHistoryMap &HistMap) {
+ EntryIndex ClobberIndex = HistMap.startClobber(Var, ClobberingInstr);
+
+ // Close all entries whose values are described by the register.
+ SmallVector<EntryIndex, 4> IndicesToErase;
+ for (auto Index : LiveEntries[Var]) {
+ auto &Entry = HistMap.getEntry(Var, Index);
+ assert(Entry.isDbgValue() && "Not a DBG_VALUE in LiveEntries");
+ if (isDescribedByReg(*Entry.getInstr()) == RegNo) {
+ IndicesToErase.push_back(Index);
+ Entry.endEntry(ClobberIndex);
+ }
+ }
+
+ // Drop all entries that have ended.
+ for (auto Index : IndicesToErase)
+ LiveEntries[Var].erase(Index);
+}
+
+/// Add a new debug value for \p Var. Closes all overlapping debug values.
+static void handleNewDebugValue(InlinedEntity Var, const MachineInstr &DV,
+ RegDescribedVarsMap &RegVars,
+ DbgValueEntriesMap &LiveEntries,
+ DbgValueHistoryMap &HistMap) {
+ EntryIndex NewIndex;
+ if (HistMap.startDbgValue(Var, DV, NewIndex)) {
+ SmallDenseMap<unsigned, bool, 4> TrackedRegs;
+
+ // If we have created a new debug value entry, close all preceding
+ // live entries that overlap.
+ SmallVector<EntryIndex, 4> IndicesToErase;
+ const DIExpression *DIExpr = DV.getDebugExpression();
+ for (auto Index : LiveEntries[Var]) {
+ auto &Entry = HistMap.getEntry(Var, Index);
+ assert(Entry.isDbgValue() && "Not a DBG_VALUE in LiveEntries");
+ const MachineInstr &DV = *Entry.getInstr();
+ bool Overlaps = DIExpr->fragmentsOverlap(DV.getDebugExpression());
+ if (Overlaps) {
+ IndicesToErase.push_back(Index);
+ Entry.endEntry(NewIndex);
+ }
+ if (unsigned Reg = isDescribedByReg(DV))
+ TrackedRegs[Reg] |= !Overlaps;
+ }
+
+ // If the new debug value is described by a register, add tracking of
+ // that register if it is not already tracked.
+ if (unsigned NewReg = isDescribedByReg(DV)) {
+ if (!TrackedRegs.count(NewReg))
+ addRegDescribedVar(RegVars, NewReg, Var);
+ LiveEntries[Var].insert(NewIndex);
+ TrackedRegs[NewReg] = true;
+ }
+
+ // Drop tracking of registers that are no longer used.
+ for (auto I : TrackedRegs)
+ if (!I.second)
+ dropRegDescribedVar(RegVars, I.first, Var);
+
+ // Drop all entries that have ended, and mark the new entry as live.
+ for (auto Index : IndicesToErase)
+ LiveEntries[Var].erase(Index);
+ LiveEntries[Var].insert(NewIndex);
+ }
+}
+
// 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,
DbgValueHistoryMap &HistMap,
+ DbgValueEntriesMap &LiveEntries,
const MachineInstr &ClobberingInstr) {
// Iterate over all variables described by this register and add this
// instruction to their history, clobbering it.
for (const auto &Var : I->second)
- HistMap.endInstrRange(Var, ClobberingInstr);
+ clobberRegEntries(Var, I->first, ClobberingInstr, LiveEntries, HistMap);
RegVars.erase(I);
}
@@ -131,115 +220,25 @@ static void clobberRegisterUses(RegDescribedVarsMap &RegVars,
// @RegNo by inserting @ClobberingInstr to their history.
static void clobberRegisterUses(RegDescribedVarsMap &RegVars, unsigned RegNo,
DbgValueHistoryMap &HistMap,
+ DbgValueEntriesMap &LiveEntries,
const MachineInstr &ClobberingInstr) {
const auto &I = RegVars.find(RegNo);
if (I == RegVars.end())
return;
- clobberRegisterUses(RegVars, I, HistMap, ClobberingInstr);
-}
-
-// 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();
- if (LastMI == MBB.end() || !LastMI->isReturn())
- return nullptr;
- // Assume that epilogue starts with instruction having the same debug location
- // as the return instruction.
- DebugLoc LastLoc = LastMI->getDebugLoc();
- auto Res = LastMI;
- for (MachineBasicBlock::const_reverse_iterator I = LastMI.getReverse(),
- E = MBB.rend();
- I != E; ++I) {
- if (I->getDebugLoc() != LastLoc)
- return &*Res;
- Res = &*I;
- }
- // If all instructions have the same debug location, assume whole MBB is
- // an epilogue.
- return &*MBB.begin();
-}
-
-// 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,
- BitVector &Regs) {
- for (const auto &MBB : *MF) {
- auto FirstEpilogueInst = getFirstEpilogueInst(MBB);
-
- for (const auto &MI : MBB) {
- // Avoid looking at prologue or epilogue instructions.
- if (&MI == FirstEpilogueInst)
- break;
- if (MI.getFlag(MachineInstr::FrameSetup))
- continue;
-
- // Look for register defs and register masks. Register masks are
- // typically on calls and they clobber everything not in the mask.
- for (const MachineOperand &MO : MI.operands()) {
- // Skip virtual registers since they are handled by the parent.
- if (MO.isReg() && MO.isDef() && MO.getReg() &&
- !TRI->isVirtualRegister(MO.getReg())) {
- for (MCRegAliasIterator AI(MO.getReg(), TRI, true); AI.isValid();
- ++AI)
- Regs.set(*AI);
- } else if (MO.isRegMask()) {
- Regs.setBitsNotInMask(MO.getRegMask());
- }
- }
- }
- }
+ clobberRegisterUses(RegVars, I, HistMap, LiveEntries, ClobberingInstr);
}
void llvm::calculateDbgEntityHistory(const MachineFunction *MF,
const TargetRegisterInfo *TRI,
DbgValueHistoryMap &DbgValues,
DbgLabelInstrMap &DbgLabels) {
- BitVector ChangingRegs(TRI->getNumRegs());
- collectChangingRegs(MF, TRI, ChangingRegs);
-
const TargetLowering *TLI = MF->getSubtarget().getTargetLowering();
unsigned SP = TLI->getStackPointerRegisterToSaveRestore();
+ unsigned FrameReg = TRI->getFrameRegister(*MF);
RegDescribedVarsMap RegVars;
+ DbgValueEntriesMap LiveEntries;
for (const auto &MBB : *MF) {
for (const auto &MI : MBB) {
- if (!MI.isDebugInstr()) {
- // Not a DBG_VALUE instruction. It may clobber registers which describe
- // some variables.
- for (const MachineOperand &MO : MI.operands()) {
- if (MO.isReg() && MO.isDef() && MO.getReg()) {
- // Ignore call instructions that claim to clobber SP. The AArch64
- // backend does this for aggregate function arguments.
- if (MI.isCall() && MO.getReg() == SP)
- continue;
- // If this is a virtual register, only clobber it since it doesn't
- // have aliases.
- if (TRI->isVirtualRegister(MO.getReg()))
- clobberRegisterUses(RegVars, MO.getReg(), DbgValues, MI);
- // If this is a register def operand, it may end a debug value
- // range.
- else {
- for (MCRegAliasIterator AI(MO.getReg(), TRI, true); AI.isValid();
- ++AI)
- if (ChangingRegs.test(*AI))
- clobberRegisterUses(RegVars, *AI, DbgValues, MI);
- }
- } else if (MO.isRegMask()) {
- // If this is a register mask operand, clobber all debug values in
- // non-CSRs.
- for (unsigned I : ChangingRegs.set_bits()) {
- // Don't consider SP to be clobbered by register masks.
- if (unsigned(I) != SP && TRI->isPhysicalRegister(I) &&
- MO.clobbersPhysReg(I)) {
- clobberRegisterUses(RegVars, I, DbgValues, MI);
- }
- }
- }
- }
- continue;
- }
-
if (MI.isDebugValue()) {
assert(MI.getNumOperands() > 1 && "Invalid DBG_VALUE instruction!");
// Use the base variable (without any DW_OP_piece expressions)
@@ -250,13 +249,7 @@ void llvm::calculateDbgEntityHistory(const MachineFunction *MF,
"Expected inlined-at fields to agree");
InlinedEntity Var(RawVar, MI.getDebugLoc()->getInlinedAt());
- if (unsigned PrevReg = DbgValues.getRegisterForVar(Var))
- dropRegDescribedVar(RegVars, PrevReg, Var);
-
- DbgValues.startInstrRange(Var, MI);
-
- if (unsigned NewReg = isDescribedByReg(MI))
- addRegDescribedVar(RegVars, NewReg, Var);
+ handleNewDebugValue(Var, MI, RegVars, LiveEntries, DbgValues);
} else if (MI.isDebugLabel()) {
assert(MI.getNumOperands() == 1 && "Invalid DBG_LABEL instruction!");
const DILabel *RawLabel = MI.getDebugLabel();
@@ -268,18 +261,75 @@ void llvm::calculateDbgEntityHistory(const MachineFunction *MF,
InlinedEntity L(RawLabel, MI.getDebugLoc()->getInlinedAt());
DbgLabels.addInstr(L, MI);
}
- }
- // Make sure locations for register-described variables are valid only
- // until the end of the basic block (unless it's the last basic block, in
- // which case let their liveness run off to the end of the function).
+ if (MI.isDebugInstr())
+ continue;
+
+ // Not a DBG_VALUE instruction. It may clobber registers which describe
+ // some variables.
+ for (const MachineOperand &MO : MI.operands()) {
+ if (MO.isReg() && MO.isDef() && MO.getReg()) {
+ // Ignore call instructions that claim to clobber SP. The AArch64
+ // backend does this for aggregate function arguments.
+ if (MI.isCall() && MO.getReg() == SP)
+ continue;
+ // If this is a virtual register, only clobber it since it doesn't
+ // have aliases.
+ if (TRI->isVirtualRegister(MO.getReg()))
+ clobberRegisterUses(RegVars, MO.getReg(), DbgValues, LiveEntries,
+ MI);
+ // If this is a register def operand, it may end a debug value
+ // range. Ignore frame-register defs in the epilogue and prologue,
+ // we expect debuggers to understand that stack-locations are
+ // invalid outside of the function body.
+ else if (MO.getReg() != FrameReg ||
+ (!MI.getFlag(MachineInstr::FrameDestroy) &&
+ !MI.getFlag(MachineInstr::FrameSetup))) {
+ for (MCRegAliasIterator AI(MO.getReg(), TRI, true); AI.isValid();
+ ++AI)
+ clobberRegisterUses(RegVars, *AI, DbgValues, LiveEntries, MI);
+ }
+ } else if (MO.isRegMask()) {
+ // If this is a register mask operand, clobber all debug values in
+ // non-CSRs.
+ SmallVector<unsigned, 32> RegsToClobber;
+ // Don't consider SP to be clobbered by register masks.
+ for (auto It : RegVars) {
+ unsigned int Reg = It.first;
+ if (Reg != SP && TRI->isPhysicalRegister(Reg) &&
+ MO.clobbersPhysReg(Reg))
+ RegsToClobber.push_back(Reg);
+ }
+
+ for (unsigned Reg : RegsToClobber) {
+ clobberRegisterUses(RegVars, Reg, DbgValues, LiveEntries, MI);
+ }
+ }
+ } // End MO loop.
+ } // End instr loop.
+
+ // Make sure locations for all variables are valid only until the end of
+ // the basic block (unless it's the last basic block, in which case let
+ // their liveness run off to the end of the function).
if (!MBB.empty() && &MBB != &MF->back()) {
- for (auto I = RegVars.begin(), E = RegVars.end(); I != E;) {
- auto CurElem = I++; // CurElem can be erased below.
- if (TRI->isVirtualRegister(CurElem->first) ||
- ChangingRegs.test(CurElem->first))
- clobberRegisterUses(RegVars, CurElem, DbgValues, MBB.back());
+ // Iterate over all variables that have open debug values.
+ for (auto &Pair : LiveEntries) {
+ if (Pair.second.empty())
+ continue;
+
+ // Create a clobbering entry.
+ EntryIndex ClobIdx = DbgValues.startClobber(Pair.first, MBB.back());
+
+ // End all entries.
+ for (EntryIndex Idx : Pair.second) {
+ DbgValueHistoryMap::Entry &Ent = DbgValues.getEntry(Pair.first, Idx);
+ assert(Ent.isDbgValue() && !Ent.isClosed());
+ Ent.endEntry(ClobIdx);
+ }
}
+
+ LiveEntries.clear();
+ RegVars.clear();
}
}
}
@@ -289,7 +339,7 @@ LLVM_DUMP_METHOD void DbgValueHistoryMap::dump() const {
dbgs() << "DbgValueHistoryMap:\n";
for (const auto &VarRangePair : *this) {
const InlinedEntity &Var = VarRangePair.first;
- const InstrRanges &Ranges = VarRangePair.second;
+ const Entries &Entries = VarRangePair.second;
const DILocalVariable *LocalVar = cast<DILocalVariable>(Var.first);
const DILocation *Location = Var.second;
@@ -304,10 +354,20 @@ LLVM_DUMP_METHOD void DbgValueHistoryMap::dump() const {
dbgs() << " --\n";
- for (const InstrRange &Range : Ranges) {
- dbgs() << " Begin: " << *Range.first;
- if (Range.second)
- dbgs() << " End : " << *Range.second;
+ for (const auto &E : enumerate(Entries)) {
+ const auto &Entry = E.value();
+ dbgs() << " Entry[" << E.index() << "]: ";
+ if (Entry.isDbgValue())
+ dbgs() << "Debug value\n";
+ else
+ dbgs() << "Clobber\n";
+ dbgs() << " Instr: " << *Entry.getInstr();
+ if (Entry.isDbgValue()) {
+ if (Entry.getEndIndex() == NoEntry)
+ dbgs() << " - Valid until end of function\n";
+ else
+ dbgs() << " - Closed by Entry[" << Entry.getEndIndex() << "]\n";
+ }
dbgs() << "\n";
}
}
diff --git a/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp b/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp
index 551cd36d1984..22f458e4b03e 100644
--- a/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp
+++ b/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp
@@ -1,9 +1,8 @@
//===-- llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp -------*- C++ -*--===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -141,10 +140,9 @@ DebugHandlerBase::getFunctionLocalOffsetAfterInsn(const MachineInstr *MI) {
}
/// 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();
+uint64_t DebugHandlerBase::getBaseTypeSize(const DIType *Ty) {
assert(Ty);
- DIDerivedType *DDTy = dyn_cast<DIDerivedType>(Ty);
+ const DIDerivedType *DDTy = dyn_cast<DIDerivedType>(Ty);
if (!DDTy)
return Ty->getSizeInBits();
@@ -155,7 +153,7 @@ uint64_t DebugHandlerBase::getBaseTypeSize(const DITypeRef TyRef) {
Tag != dwarf::DW_TAG_restrict_type && Tag != dwarf::DW_TAG_atomic_type)
return DDTy->getSizeInBits();
- DIType *BaseType = DDTy->getBaseType().resolve();
+ DIType *BaseType = DDTy->getBaseType();
if (!BaseType)
return 0;
@@ -212,36 +210,58 @@ void DebugHandlerBase::beginFunction(const MachineFunction *MF) {
// Request labels for the full history.
for (const auto &I : DbgValues) {
- const auto &Ranges = I.second;
- if (Ranges.empty())
+ const auto &Entries = I.second;
+ if (Entries.empty())
continue;
- // The first mention of a function argument gets the CurrentFnBegin
- // label, so arguments are visible when breaking at function entry.
- const DILocalVariable *DIVar = Ranges.front().first->getDebugVariable();
+ auto IsDescribedByReg = [](const MachineInstr *MI) {
+ return MI->getOperand(0).isReg() && MI->getOperand(0).getReg();
+ };
+
+ // The first mention of a function argument gets the CurrentFnBegin label,
+ // so arguments are visible when breaking at function entry.
+ //
+ // We do not change the label for values that are described by registers,
+ // as that could place them above their defining instructions. We should
+ // ideally not change the labels for constant debug values either, since
+ // doing that violates the ranges that are calculated in the history map.
+ // However, we currently do not emit debug values for constant arguments
+ // directly at the start of the function, so this code is still useful.
+ const DILocalVariable *DIVar =
+ Entries.front().getInstr()->getDebugVariable();
if (DIVar->isParameter() &&
getDISubprogram(DIVar->getScope())->describes(&MF->getFunction())) {
- LabelsBeforeInsn[Ranges.front().first] = Asm->getFunctionBegin();
- if (Ranges.front().first->getDebugExpression()->isFragment()) {
+ if (!IsDescribedByReg(Entries.front().getInstr()))
+ LabelsBeforeInsn[Entries.front().getInstr()] = Asm->getFunctionBegin();
+ if (Entries.front().getInstr()->getDebugExpression()->isFragment()) {
// Mark all non-overlapping initial fragments.
- for (auto I = Ranges.begin(); I != Ranges.end(); ++I) {
- const DIExpression *Fragment = I->first->getDebugExpression();
- if (std::all_of(Ranges.begin(), I,
- [&](DbgValueHistoryMap::InstrRange Pred) {
- return !Fragment->fragmentsOverlap(
- Pred.first->getDebugExpression());
+ for (auto I = Entries.begin(); I != Entries.end(); ++I) {
+ if (!I->isDbgValue())
+ continue;
+ const DIExpression *Fragment = I->getInstr()->getDebugExpression();
+ if (std::any_of(Entries.begin(), I,
+ [&](DbgValueHistoryMap::Entry Pred) {
+ return Pred.isDbgValue() &&
+ Fragment->fragmentsOverlap(
+ Pred.getInstr()->getDebugExpression());
}))
- LabelsBeforeInsn[I->first] = Asm->getFunctionBegin();
- else
break;
+ // The code that generates location lists for DWARF assumes that the
+ // entries' start labels are monotonically increasing, and since we
+ // don't change the label for fragments that are described by
+ // registers, we must bail out when encountering such a fragment.
+ if (IsDescribedByReg(I->getInstr()))
+ break;
+ LabelsBeforeInsn[I->getInstr()] = Asm->getFunctionBegin();
}
}
}
- for (const auto &Range : Ranges) {
- requestLabelBeforeInsn(Range.first);
- if (Range.second)
- requestLabelAfterInsn(Range.second);
+ for (const auto &Entry : Entries) {
+ if (Entry.isDbgValue())
+ requestLabelBeforeInsn(Entry.getInstr());
+ else
+ requestLabelAfterInsn(Entry.getInstr());
}
}
diff --git a/lib/CodeGen/AsmPrinter/DebugLocEntry.h b/lib/CodeGen/AsmPrinter/DebugLocEntry.h
index befa4b941c8d..17e39b3d3268 100644
--- a/lib/CodeGen/AsmPrinter/DebugLocEntry.h
+++ b/lib/CodeGen/AsmPrinter/DebugLocEntry.h
@@ -1,9 +1,8 @@
//===-- llvm/CodeGen/DebugLocEntry.h - Entry in debug_loc list -*- C++ -*--===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
@@ -21,6 +20,73 @@
namespace llvm {
class AsmPrinter;
+/// A single location or constant.
+class DbgValueLoc {
+ /// Any complex address location expression for this DbgValueLoc.
+ const DIExpression *Expression;
+
+ /// Type of entry that this represents.
+ enum EntryType { E_Location, E_Integer, E_ConstantFP, E_ConstantInt };
+ enum EntryType EntryKind;
+
+ /// Either a constant,
+ union {
+ int64_t Int;
+ const ConstantFP *CFP;
+ const ConstantInt *CIP;
+ } Constant;
+
+ /// Or a location in the machine frame.
+ MachineLocation Loc;
+
+public:
+ DbgValueLoc(const DIExpression *Expr, int64_t i)
+ : Expression(Expr), EntryKind(E_Integer) {
+ Constant.Int = i;
+ }
+ DbgValueLoc(const DIExpression *Expr, const ConstantFP *CFP)
+ : Expression(Expr), EntryKind(E_ConstantFP) {
+ Constant.CFP = CFP;
+ }
+ DbgValueLoc(const DIExpression *Expr, const ConstantInt *CIP)
+ : Expression(Expr), EntryKind(E_ConstantInt) {
+ Constant.CIP = CIP;
+ }
+ DbgValueLoc(const DIExpression *Expr, MachineLocation Loc)
+ : Expression(Expr), EntryKind(E_Location), Loc(Loc) {
+ assert(cast<DIExpression>(Expr)->isValid());
+ }
+
+ bool isLocation() const { return EntryKind == E_Location; }
+ bool isInt() const { return EntryKind == E_Integer; }
+ bool isConstantFP() const { return EntryKind == E_ConstantFP; }
+ bool isConstantInt() const { return EntryKind == E_ConstantInt; }
+ int64_t getInt() const { return Constant.Int; }
+ const ConstantFP *getConstantFP() const { return Constant.CFP; }
+ const ConstantInt *getConstantInt() const { return Constant.CIP; }
+ MachineLocation getLoc() const { return Loc; }
+ bool isFragment() const { return getExpression()->isFragment(); }
+ bool isEntryVal() const { return getExpression()->isEntryValue(); }
+ const DIExpression *getExpression() const { return Expression; }
+ friend bool operator==(const DbgValueLoc &, const DbgValueLoc &);
+ friend bool operator<(const DbgValueLoc &, const DbgValueLoc &);
+#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
+ LLVM_DUMP_METHOD void dump() const {
+ if (isLocation()) {
+ llvm::dbgs() << "Loc = { reg=" << Loc.getReg() << " ";
+ if (Loc.isIndirect())
+ llvm::dbgs() << "+0";
+ llvm::dbgs() << "} ";
+ } else if (isConstantInt())
+ Constant.CIP->dump();
+ else if (isConstantFP())
+ Constant.CFP->dump();
+ if (Expression)
+ Expression->dump();
+ }
+#endif
+};
+
/// This struct describes location entries emitted in the .debug_loc
/// section.
class DebugLocEntry {
@@ -28,90 +94,20 @@ class DebugLocEntry {
const MCSymbol *Begin;
const MCSymbol *End;
-public:
- /// A single location or constant.
- struct Value {
- Value(const DIExpression *Expr, int64_t i)
- : Expression(Expr), EntryKind(E_Integer) {
- Constant.Int = i;
- }
- Value(const DIExpression *Expr, const ConstantFP *CFP)
- : Expression(Expr), EntryKind(E_ConstantFP) {
- Constant.CFP = CFP;
- }
- Value(const DIExpression *Expr, const ConstantInt *CIP)
- : Expression(Expr), EntryKind(E_ConstantInt) {
- Constant.CIP = CIP;
- }
- Value(const DIExpression *Expr, MachineLocation Loc)
- : Expression(Expr), EntryKind(E_Location), Loc(Loc) {
- assert(cast<DIExpression>(Expr)->isValid());
- }
-
- /// Any complex address location expression for this Value.
- const DIExpression *Expression;
-
- /// Type of entry that this represents.
- enum EntryType { E_Location, E_Integer, E_ConstantFP, E_ConstantInt };
- enum EntryType EntryKind;
-
- /// Either a constant,
- union {
- int64_t Int;
- const ConstantFP *CFP;
- const ConstantInt *CIP;
- } Constant;
-
- // Or a location in the machine frame.
- MachineLocation Loc;
-
- bool isLocation() const { return EntryKind == E_Location; }
- bool isInt() const { return EntryKind == E_Integer; }
- bool isConstantFP() const { return EntryKind == E_ConstantFP; }
- bool isConstantInt() const { return EntryKind == E_ConstantInt; }
- int64_t getInt() const { return Constant.Int; }
- const ConstantFP *getConstantFP() const { return Constant.CFP; }
- const ConstantInt *getConstantInt() const { return Constant.CIP; }
- MachineLocation getLoc() const { return Loc; }
- bool isFragment() const { return getExpression()->isFragment(); }
- const DIExpression *getExpression() const { return Expression; }
- friend bool operator==(const Value &, const Value &);
- friend bool operator<(const Value &, const Value &);
-#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
- LLVM_DUMP_METHOD void dump() const {
- if (isLocation()) {
- llvm::dbgs() << "Loc = { reg=" << Loc.getReg() << " ";
- if (Loc.isIndirect())
- llvm::dbgs() << "+0";
- llvm::dbgs() << "} ";
- }
- else if (isConstantInt())
- Constant.CIP->dump();
- else if (isConstantFP())
- Constant.CFP->dump();
- if (Expression)
- Expression->dump();
- }
-#endif
- };
-
-private:
/// A nonempty list of locations/constants belonging to this entry,
/// sorted by offset.
- SmallVector<Value, 1> Values;
+ SmallVector<DbgValueLoc, 1> Values;
public:
- DebugLocEntry(const MCSymbol *B, const MCSymbol *E, Value Val)
- : Begin(B), End(E) {
- Values.push_back(std::move(Val));
+ /// Create a location list entry for the range [\p Begin, \p End).
+ ///
+ /// \param Vals One or more values describing (parts of) the variable.
+ DebugLocEntry(const MCSymbol *Begin, const MCSymbol *End,
+ ArrayRef<DbgValueLoc> Vals)
+ : Begin(Begin), End(End) {
+ addValues(Vals);
}
- /// 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);
-
/// 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
@@ -127,35 +123,36 @@ public:
const MCSymbol *getBeginSym() const { return Begin; }
const MCSymbol *getEndSym() const { return End; }
- ArrayRef<Value> getValues() const { return Values; }
- void addValues(ArrayRef<DebugLocEntry::Value> Vals) {
+ ArrayRef<DbgValueLoc> getValues() const { return Values; }
+ void addValues(ArrayRef<DbgValueLoc> Vals) {
Values.append(Vals.begin(), Vals.end());
sortUniqueValues();
- assert(all_of(Values, [](DebugLocEntry::Value V) {
- return V.isFragment();
- }) && "value must be a piece");
+ assert((Values.size() == 1 || all_of(Values, [](DbgValueLoc V) {
+ return V.isFragment();
+ })) && "must either have a single value or multiple pieces");
}
// Sort the pieces by offset.
// Remove any duplicate entries by dropping all but the first.
void sortUniqueValues() {
llvm::sort(Values);
- Values.erase(
- std::unique(
- Values.begin(), Values.end(), [](const Value &A, const Value &B) {
- return A.getExpression() == B.getExpression();
- }),
- Values.end());
+ Values.erase(std::unique(Values.begin(), Values.end(),
+ [](const DbgValueLoc &A, const DbgValueLoc &B) {
+ return A.getExpression() == B.getExpression();
+ }),
+ Values.end());
}
/// Lower this entry into a DWARF expression.
- void finalize(const AsmPrinter &AP, DebugLocStream::ListBuilder &List,
- const DIBasicType *BT);
+ void finalize(const AsmPrinter &AP,
+ DebugLocStream::ListBuilder &List,
+ const DIBasicType *BT,
+ DwarfCompileUnit &TheCU);
};
-/// Compare two Values for equality.
-inline bool operator==(const DebugLocEntry::Value &A,
- const DebugLocEntry::Value &B) {
+/// Compare two DbgValueLocs for equality.
+inline bool operator==(const DbgValueLoc &A,
+ const DbgValueLoc &B) {
if (A.EntryKind != B.EntryKind)
return false;
@@ -163,21 +160,21 @@ inline bool operator==(const DebugLocEntry::Value &A,
return false;
switch (A.EntryKind) {
- case DebugLocEntry::Value::E_Location:
+ case DbgValueLoc::E_Location:
return A.Loc == B.Loc;
- case DebugLocEntry::Value::E_Integer:
+ case DbgValueLoc::E_Integer:
return A.Constant.Int == B.Constant.Int;
- case DebugLocEntry::Value::E_ConstantFP:
+ case DbgValueLoc::E_ConstantFP:
return A.Constant.CFP == B.Constant.CFP;
- case DebugLocEntry::Value::E_ConstantInt:
+ case DbgValueLoc::E_ConstantInt:
return A.Constant.CIP == B.Constant.CIP;
}
llvm_unreachable("unhandled EntryKind");
}
/// Compare two fragments based on their offset.
-inline bool operator<(const DebugLocEntry::Value &A,
- const DebugLocEntry::Value &B) {
+inline bool operator<(const DbgValueLoc &A,
+ const DbgValueLoc &B) {
return A.getExpression()->getFragmentInfo()->OffsetInBits <
B.getExpression()->getFragmentInfo()->OffsetInBits;
}
diff --git a/lib/CodeGen/AsmPrinter/DebugLocStream.cpp b/lib/CodeGen/AsmPrinter/DebugLocStream.cpp
index 7e8ed7104af3..f483d532ff07 100644
--- a/lib/CodeGen/AsmPrinter/DebugLocStream.cpp
+++ b/lib/CodeGen/AsmPrinter/DebugLocStream.cpp
@@ -1,9 +1,8 @@
//===- DebugLocStream.cpp - DWARF debug_loc stream --------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
diff --git a/lib/CodeGen/AsmPrinter/DebugLocStream.h b/lib/CodeGen/AsmPrinter/DebugLocStream.h
index 8dcf5cbc1889..789291771b5a 100644
--- a/lib/CodeGen/AsmPrinter/DebugLocStream.h
+++ b/lib/CodeGen/AsmPrinter/DebugLocStream.h
@@ -1,9 +1,8 @@
//===--- lib/CodeGen/DebugLocStream.h - DWARF debug_loc stream --*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
diff --git a/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp b/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp
index 1990456cc555..207a7284dafa 100644
--- a/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp
+++ b/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp
@@ -1,9 +1,8 @@
//===-- CodeGen/AsmPrinter/DwarfException.cpp - Dwarf Exception Impl ------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
diff --git a/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp b/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
index 1dca3f0fce5b..9548ad9918c1 100644
--- a/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
+++ b/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
@@ -1,9 +1,8 @@
//===- llvm/CodeGen/DwarfCompileUnit.cpp - Dwarf Compile Units ------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -18,6 +17,7 @@
#include "DwarfUnit.h"
#include "llvm/ADT/None.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/BinaryFormat/Dwarf.h"
@@ -104,7 +104,7 @@ unsigned DwarfCompileUnit::getOrCreateSourceID(const DIFile *File) {
// 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, "", "", None, None, CUID);
return Asm->OutStreamer->EmitDwarfFileDirective(
0, File->getDirectory(), File->getFilename(), getMD5AsBytes(File),
File->getSource(), CUID);
@@ -119,17 +119,19 @@ DIE *DwarfCompileUnit::getOrCreateGlobalVariableDIE(
assert(GV);
auto *GVContext = GV->getScope();
- auto *GTy = DD->resolve(GV->getType());
+ const DIType *GTy = GV->getType();
// Construct the context before querying for the existence of the DIE in
// case such construction creates the DIE.
- DIE *ContextDIE = getOrCreateContextDIE(GVContext);
+ auto *CB = GVContext ? dyn_cast<DICommonBlock>(GVContext) : nullptr;
+ DIE *ContextDIE = CB ? getOrCreateCommonBlock(CB, GlobalExprs)
+ : getOrCreateContextDIE(GVContext);
// Add to map.
DIE *VariableDIE = &createAndAddDIE(GV->getTag(), *ContextDIE, GV);
DIScope *DeclContext;
if (auto *SDMDecl = GV->getStaticDataMemberDeclaration()) {
- DeclContext = resolve(SDMDecl->getScope());
+ DeclContext = SDMDecl->getScope();
assert(SDMDecl->isStaticMember() && "Expected static member decl");
assert(GV->isDefinition());
// We need the declaration DIE that is in the static member's class.
@@ -137,7 +139,7 @@ DIE *DwarfCompileUnit::getOrCreateGlobalVariableDIE(
addDIEEntry(*VariableDIE, dwarf::DW_AT_specification, *VariableSpecDIE);
// If the global variable's type is different from the one in the class
// member type, assume that it's more specific and also emit it.
- if (GTy != DD->resolve(SDMDecl->getBaseType()))
+ if (GTy != SDMDecl->getBaseType())
addType(*VariableDIE, GTy);
} else {
DeclContext = GV->getScope();
@@ -166,8 +168,16 @@ DIE *DwarfCompileUnit::getOrCreateGlobalVariableDIE(
addTemplateParams(*VariableDIE, DINodeArray(TP));
// Add location.
+ addLocationAttribute(VariableDIE, GV, GlobalExprs);
+
+ return VariableDIE;
+}
+
+void DwarfCompileUnit::addLocationAttribute(
+ DIE *VariableDIE, const DIGlobalVariable *GV, ArrayRef<GlobalExpr> GlobalExprs) {
bool addToAccelTable = false;
DIELoc *Loc = nullptr;
+ Optional<unsigned> NVPTXAddressSpace;
std::unique_ptr<DIEDwarfExpression> DwarfExpr;
for (const auto &GE : GlobalExprs) {
const GlobalVariable *Global = GE.Var;
@@ -201,8 +211,24 @@ DIE *DwarfCompileUnit::getOrCreateGlobalVariableDIE(
DwarfExpr = llvm::make_unique<DIEDwarfExpression>(*Asm, *this, *Loc);
}
- if (Expr)
+ if (Expr) {
+ // According to
+ // https://docs.nvidia.com/cuda/archive/10.0/ptx-writers-guide-to-interoperability/index.html#cuda-specific-dwarf
+ // cuda-gdb requires DW_AT_address_class for all variables to be able to
+ // correctly interpret address space of the variable address.
+ // Decode DW_OP_constu <DWARF Address Space> DW_OP_swap DW_OP_xderef
+ // sequence for the NVPTX + gdb target.
+ unsigned LocalNVPTXAddressSpace;
+ if (Asm->TM.getTargetTriple().isNVPTX() && DD->tuneForGDB()) {
+ const DIExpression *NewExpr =
+ DIExpression::extractAddressClass(Expr, LocalNVPTXAddressSpace);
+ if (NewExpr != Expr) {
+ Expr = NewExpr;
+ NVPTXAddressSpace = LocalNVPTXAddressSpace;
+ }
+ }
DwarfExpr->addFragmentOffset(Expr);
+ }
if (Global) {
const MCSymbol *Sym = Asm->getSymbol(Global);
@@ -247,6 +273,15 @@ DIE *DwarfCompileUnit::getOrCreateGlobalVariableDIE(
DwarfExpr->setMemoryLocationKind();
DwarfExpr->addExpression(Expr);
}
+ if (Asm->TM.getTargetTriple().isNVPTX() && DD->tuneForGDB()) {
+ // According to
+ // https://docs.nvidia.com/cuda/archive/10.0/ptx-writers-guide-to-interoperability/index.html#cuda-specific-dwarf
+ // cuda-gdb requires DW_AT_address_class for all variables to be able to
+ // correctly interpret address space of the variable address.
+ const unsigned NVPTX_ADDR_global_space = 5;
+ addUInt(*VariableDIE, dwarf::DW_AT_address_class, dwarf::DW_FORM_data1,
+ NVPTXAddressSpace ? *NVPTXAddressSpace : NVPTX_ADDR_global_space);
+ }
if (Loc)
addBlock(*VariableDIE, dwarf::DW_AT_location, DwarfExpr->finalize());
@@ -262,8 +297,25 @@ DIE *DwarfCompileUnit::getOrCreateGlobalVariableDIE(
DD->useAllLinkageNames())
DD->addAccelName(*CUNode, GV->getLinkageName(), *VariableDIE);
}
+}
- return VariableDIE;
+DIE *DwarfCompileUnit::getOrCreateCommonBlock(
+ const DICommonBlock *CB, ArrayRef<GlobalExpr> GlobalExprs) {
+ // Construct the context before querying for the existence of the DIE in case
+ // such construction creates the DIE.
+ DIE *ContextDIE = getOrCreateContextDIE(CB->getScope());
+
+ if (DIE *NDie = getDIE(CB))
+ return NDie;
+ DIE &NDie = createAndAddDIE(dwarf::DW_TAG_common_block, *ContextDIE, CB);
+ StringRef Name = CB->getName().empty() ? "_BLNK_" : CB->getName();
+ addString(NDie, dwarf::DW_AT_name, Name);
+ addGlobalName(Name, NDie, CB->getScope());
+ if (CB->getFile())
+ addSourceLine(NDie, CB->getLineNo(), CB->getFile());
+ if (DIGlobalVariable *V = CB->getDecl())
+ getCU().addLocationAttribute(&NDie, V, GlobalExprs);
+ return &NDie;
}
void DwarfCompileUnit::addRange(RangeSpan Range) {
@@ -491,6 +543,8 @@ DIE *DwarfCompileUnit::constructInlinedScopeDIE(LexicalScope *Scope) {
addUInt(*ScopeDIE, dwarf::DW_AT_call_file, None,
getOrCreateSourceID(IA->getFile()));
addUInt(*ScopeDIE, dwarf::DW_AT_call_line, None, IA->getLine());
+ if (IA->getColumn())
+ addUInt(*ScopeDIE, dwarf::DW_AT_call_column, None, IA->getColumn());
if (IA->getDiscriminator() && DD->getDwarfVersion() >= 4)
addUInt(*ScopeDIE, dwarf::DW_AT_GNU_discriminator, None,
IA->getDiscriminator());
@@ -555,36 +609,27 @@ DIE *DwarfCompileUnit::constructVariableDIEImpl(const DbgVariable &DV,
return VariableDie;
}
- // Check if variable is described by a DBG_VALUE instruction.
- if (const MachineInstr *DVInsn = DV.getMInsn()) {
- assert(DVInsn->getNumOperands() == 4);
- if (DVInsn->getOperand(0).isReg()) {
- auto RegOp = DVInsn->getOperand(0);
- auto Op1 = DVInsn->getOperand(1);
- // If the second operand is an immediate, this is an indirect value.
- assert((!Op1.isImm() || (Op1.getImm() == 0)) && "unexpected offset");
- MachineLocation Location(RegOp.getReg(), Op1.isImm());
- addVariableAddress(DV, *VariableDie, Location);
- } else if (DVInsn->getOperand(0).isImm()) {
- // This variable is described by a single constant.
- // Check whether it has a DIExpression.
+ // Check if variable has a single location description.
+ if (auto *DVal = DV.getValueLoc()) {
+ if (DVal->isLocation())
+ addVariableAddress(DV, *VariableDie, DVal->getLoc());
+ else if (DVal->isInt()) {
auto *Expr = DV.getSingleExpression();
if (Expr && Expr->getNumElements()) {
DIELoc *Loc = new (DIEValueAllocator) DIELoc;
DIEDwarfExpression DwarfExpr(*Asm, *this, *Loc);
// If there is an expression, emit raw unsigned bytes.
DwarfExpr.addFragmentOffset(Expr);
- DwarfExpr.addUnsignedConstant(DVInsn->getOperand(0).getImm());
+ DwarfExpr.addUnsignedConstant(DVal->getInt());
DwarfExpr.addExpression(Expr);
addBlock(*VariableDie, dwarf::DW_AT_location, DwarfExpr.finalize());
} else
- addConstantValue(*VariableDie, DVInsn->getOperand(0), DV.getType());
- } else if (DVInsn->getOperand(0).isFPImm())
- addConstantFPValue(*VariableDie, DVInsn->getOperand(0));
- else if (DVInsn->getOperand(0).isCImm())
- addConstantValue(*VariableDie, DVInsn->getOperand(0).getCImm(),
- DV.getType());
-
+ addConstantValue(*VariableDie, DVal->getInt(), DV.getType());
+ } else if (DVal->isConstantFP()) {
+ addConstantFPValue(*VariableDie, DVal->getConstantFP());
+ } else if (DVal->isConstantInt()) {
+ addConstantValue(*VariableDie, DVal->getConstantInt(), DV.getType());
+ }
return VariableDie;
}
@@ -592,6 +637,7 @@ DIE *DwarfCompileUnit::constructVariableDIEImpl(const DbgVariable &DV,
if (!DV.hasFrameIndexExprs())
return VariableDie;
+ Optional<unsigned> NVPTXAddressSpace;
DIELoc *Loc = new (DIEValueAllocator) DIELoc;
DIEDwarfExpression DwarfExpr(*Asm, *this, *Loc);
for (auto &Fragment : DV.getFrameIndexExprs()) {
@@ -603,7 +649,23 @@ DIE *DwarfCompileUnit::constructVariableDIEImpl(const DbgVariable &DV,
SmallVector<uint64_t, 8> Ops;
Ops.push_back(dwarf::DW_OP_plus_uconst);
Ops.push_back(Offset);
- Ops.append(Expr->elements_begin(), Expr->elements_end());
+ // According to
+ // https://docs.nvidia.com/cuda/archive/10.0/ptx-writers-guide-to-interoperability/index.html#cuda-specific-dwarf
+ // cuda-gdb requires DW_AT_address_class for all variables to be able to
+ // correctly interpret address space of the variable address.
+ // Decode DW_OP_constu <DWARF Address Space> DW_OP_swap DW_OP_xderef
+ // sequence for the NVPTX + gdb target.
+ unsigned LocalNVPTXAddressSpace;
+ if (Asm->TM.getTargetTriple().isNVPTX() && DD->tuneForGDB()) {
+ const DIExpression *NewExpr =
+ DIExpression::extractAddressClass(Expr, LocalNVPTXAddressSpace);
+ if (NewExpr != Expr) {
+ Expr = NewExpr;
+ NVPTXAddressSpace = LocalNVPTXAddressSpace;
+ }
+ }
+ if (Expr)
+ Ops.append(Expr->elements_begin(), Expr->elements_end());
DIExpressionCursor Cursor(Ops);
DwarfExpr.setMemoryLocationKind();
if (const MCSymbol *FrameSymbol = Asm->getFunctionFrameSymbol())
@@ -613,7 +675,19 @@ DIE *DwarfCompileUnit::constructVariableDIEImpl(const DbgVariable &DV,
*Asm->MF->getSubtarget().getRegisterInfo(), Cursor, FrameReg);
DwarfExpr.addExpression(std::move(Cursor));
}
+ if (Asm->TM.getTargetTriple().isNVPTX() && DD->tuneForGDB()) {
+ // According to
+ // https://docs.nvidia.com/cuda/archive/10.0/ptx-writers-guide-to-interoperability/index.html#cuda-specific-dwarf
+ // cuda-gdb requires DW_AT_address_class for all variables to be able to
+ // correctly interpret address space of the variable address.
+ const unsigned NVPTX_ADDR_local_space = 6;
+ addUInt(*VariableDie, dwarf::DW_AT_address_class, dwarf::DW_FORM_data1,
+ NVPTXAddressSpace ? *NVPTXAddressSpace : NVPTX_ADDR_local_space);
+ }
addBlock(*VariableDie, dwarf::DW_AT_location, DwarfExpr.finalize());
+ if (DwarfExpr.TagOffset)
+ addUInt(*VariableDie, dwarf::DW_AT_LLVM_tag_offset, dwarf::DW_FORM_data1,
+ *DwarfExpr.TagOffset);
return VariableDie;
}
@@ -800,7 +874,7 @@ void DwarfCompileUnit::constructAbstractSubprogramScopeDIE(
ContextDIE = &getUnitDie();
getOrCreateSubprogramDIE(SPDecl);
} else {
- ContextDIE = getOrCreateContextDIE(resolve(SP->getScope()));
+ ContextDIE = getOrCreateContextDIE(SP->getScope());
// The scope may be shared with a subprogram that has already been
// constructed in another CU, in which case we need to construct this
// subprogram in the same CU.
@@ -849,7 +923,7 @@ DIE *DwarfCompileUnit::constructImportedEntityDIE(
DIE *IMDie = DIE::get(DIEValueAllocator, (dwarf::Tag)Module->getTag());
insertDIE(Module, IMDie);
DIE *EntityDie;
- auto *Entity = resolve(Module->getEntity());
+ auto *Entity = Module->getEntity();
if (auto *NS = dyn_cast<DINamespace>(Entity))
EntityDie = getOrCreateNameSpace(NS);
else if (auto *M = dyn_cast<DIModule>(Entity))
@@ -958,7 +1032,9 @@ bool DwarfCompileUnit::hasDwarfPubSections() const {
return true;
case DICompileUnit::DebugNameTableKind::Default:
return DD->tuneForGDB() && !includeMinimalInlineScopes() &&
- !CUNode->isDebugDirectivesOnly();
+ !CUNode->isDebugDirectivesOnly() &&
+ DD->getAccelTableKind() != AccelTableKind::Apple &&
+ DD->getDwarfVersion() < 5;
}
llvm_unreachable("Unhandled DICompileUnit::DebugNameTableKind enum");
}
@@ -1054,6 +1130,12 @@ void DwarfCompileUnit::addComplexAddress(const DbgVariable &DV, DIE &Die,
DwarfExpr.setMemoryLocationKind();
DIExpressionCursor Cursor(DIExpr);
+
+ if (DIExpr->isEntryValue()) {
+ DwarfExpr.setEntryValueFlag();
+ DwarfExpr.addEntryValueExpression(Cursor);
+ }
+
const TargetRegisterInfo &TRI = *Asm->MF->getSubtarget().getRegisterInfo();
if (!DwarfExpr.addMachineRegExpression(TRI, Cursor, Location.getReg()))
return;
@@ -1112,7 +1194,7 @@ void DwarfCompileUnit::addAddressExpr(DIE &Die, dwarf::Attribute Attribute,
void DwarfCompileUnit::applySubprogramAttributesToDefinition(
const DISubprogram *SP, DIE &SPDie) {
auto *SPDecl = SP->getDeclaration();
- auto *Context = resolve(SPDecl ? SPDecl->getScope() : SP->getScope());
+ auto *Context = SPDecl ? SPDecl->getScope() : SP->getScope();
applySubprogramAttributes(SP, SPDie, includeMinimalInlineScopes());
addGlobalName(SP->getName(), SPDie, Context);
}
@@ -1121,6 +1203,10 @@ bool DwarfCompileUnit::isDwoUnit() const {
return DD->useSplitDwarf() && Skeleton;
}
+void DwarfCompileUnit::finishNonUnitTypeDIE(DIE& D, const DICompositeType *CTy) {
+ constructTypeDIE(D, CTy);
+}
+
bool DwarfCompileUnit::includeMinimalInlineScopes() const {
return getCUNode()->getEmissionKind() == DICompileUnit::LineTablesOnly ||
(DD->useSplitDwarf() && !Skeleton);
@@ -1134,3 +1220,27 @@ void DwarfCompileUnit::addAddrTableBase() {
: dwarf::DW_AT_GNU_addr_base,
Label, TLOF.getDwarfAddrSection()->getBeginSymbol());
}
+
+void DwarfCompileUnit::addBaseTypeRef(DIEValueList &Die, int64_t Idx) {
+ Die.addValue(DIEValueAllocator, (dwarf::Attribute)0, dwarf::DW_FORM_udata,
+ new (DIEValueAllocator) DIEBaseTypeRef(this, Idx));
+}
+
+void DwarfCompileUnit::createBaseTypeDIEs() {
+ // Insert the base_type DIEs directly after the CU so that their offsets will
+ // fit in the fixed size ULEB128 used inside the location expressions.
+ // Maintain order by iterating backwards and inserting to the front of CU
+ // child list.
+ for (auto &Btr : reverse(ExprRefedBaseTypes)) {
+ DIE &Die = getUnitDie().addChildFront(
+ DIE::get(DIEValueAllocator, dwarf::DW_TAG_base_type));
+ SmallString<32> Str;
+ addString(Die, dwarf::DW_AT_name,
+ Twine(dwarf::AttributeEncodingString(Btr.Encoding) +
+ "_" + Twine(Btr.BitSize)).toStringRef(Str));
+ addUInt(Die, dwarf::DW_AT_encoding, dwarf::DW_FORM_data1, Btr.Encoding);
+ addUInt(Die, dwarf::DW_AT_byte_size, None, Btr.BitSize / 8);
+
+ Btr.Die = &Die;
+ }
+}
diff --git a/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h b/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h
index 9ec22f68c12f..ea980dfda17e 100644
--- a/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h
+++ b/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h
@@ -1,9 +1,8 @@
//===- llvm/CodeGen/DwarfCompileUnit.h - Dwarf Compile Unit -----*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -101,6 +100,8 @@ class DwarfCompileUnit final : public DwarfUnit {
return DU->getAbstractEntities();
}
+ void finishNonUnitTypeDIE(DIE& D, const DICompositeType *CTy) override;
+
public:
DwarfCompileUnit(unsigned UID, const DICompileUnit *Node, AsmPrinter *A,
DwarfDebug *DW, DwarfFile *DWU);
@@ -125,11 +126,27 @@ public:
const DIExpression *Expr;
};
+ struct BaseTypeRef {
+ BaseTypeRef(unsigned BitSize, dwarf::TypeKind Encoding) :
+ BitSize(BitSize), Encoding(Encoding) {}
+ unsigned BitSize;
+ dwarf::TypeKind Encoding;
+ DIE *Die = nullptr;
+ };
+
+ std::vector<BaseTypeRef> ExprRefedBaseTypes;
+
/// Get or create global variable DIE.
DIE *
getOrCreateGlobalVariableDIE(const DIGlobalVariable *GV,
ArrayRef<GlobalExpr> GlobalExprs);
+ DIE *getOrCreateCommonBlock(const DICommonBlock *CB,
+ ArrayRef<GlobalExpr> GlobalExprs);
+
+ void addLocationAttribute(DIE *ToDIE, const DIGlobalVariable *GV,
+ ArrayRef<GlobalExpr> GlobalExprs);
+
/// addLabelAddress - Add a dwarf label attribute data and value using
/// either DW_FORM_addr or DW_FORM_GNU_addr_index.
void addLabelAddress(DIE &Die, dwarf::Attribute Attribute,
@@ -200,6 +217,8 @@ public:
SmallVectorImpl<DIE *> &Children,
bool *HasNonScopeChildren = nullptr);
+ void createBaseTypeDIEs();
+
/// Construct a DIE for this subprogram scope.
DIE &constructSubprogramScopeDIE(const DISubprogram *Sub,
LexicalScope *Scope);
@@ -314,6 +333,8 @@ public:
void setDWOId(uint64_t DwoId) { DWOId = DwoId; }
bool hasDwarfPubSections() const;
+
+ void addBaseTypeRef(DIEValueList &Die, int64_t Idx);
};
} // end namespace llvm
diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
index 1de2ffb6cfa1..71bb2b0858cc 100644
--- a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
+++ b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
@@ -1,9 +1,8 @@
//===- llvm/CodeGen/DwarfDebug.cpp - Dwarf Debug Framework ----------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -42,6 +41,8 @@
#include "llvm/CodeGen/TargetInstrInfo.h"
#include "llvm/CodeGen/TargetRegisterInfo.h"
#include "llvm/CodeGen/TargetSubtargetInfo.h"
+#include "llvm/DebugInfo/DWARF/DWARFExpression.h"
+#include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DebugInfoMetadata.h"
#include "llvm/IR/DebugLoc.h"
@@ -162,6 +163,7 @@ static const char *const DWARFGroupName = "dwarf";
static const char *const DWARFGroupDescription = "DWARF Emission";
static const char *const DbgTimerName = "writer";
static const char *const DbgTimerDescription = "DWARF Debug Writer";
+static constexpr unsigned ULEB128PadSize = 4;
void DebugLocDwarfExpression::emitOp(uint8_t Op, const char *Comment) {
BS.EmitInt8(
@@ -177,6 +179,15 @@ void DebugLocDwarfExpression::emitUnsigned(uint64_t Value) {
BS.EmitULEB128(Value, Twine(Value));
}
+void DebugLocDwarfExpression::emitData1(uint8_t Value) {
+ BS.EmitInt8(Value, Twine(Value));
+}
+
+void DebugLocDwarfExpression::emitBaseTypeRef(uint64_t Idx) {
+ assert(Idx < (1ULL << (ULEB128PadSize * 7)) && "Idx wont fit");
+ BS.EmitULEB128(Idx, Twine(Idx), ULEB128PadSize);
+}
+
bool DebugLocDwarfExpression::isFrameRegister(const TargetRegisterInfo &TRI,
unsigned MachineReg) {
// This information is not available while emitting .debug_loc entries.
@@ -185,11 +196,11 @@ bool DebugLocDwarfExpression::isFrameRegister(const TargetRegisterInfo &TRI,
bool DbgVariable::isBlockByrefVariable() const {
assert(getVariable() && "Invalid complex DbgVariable!");
- return getVariable()->getType().resolve()->isBlockByrefStruct();
+ return getVariable()->getType()->isBlockByrefStruct();
}
const DIType *DbgVariable::getType() const {
- DIType *Ty = getVariable()->getType().resolve();
+ DIType *Ty = getVariable()->getType();
// FIXME: isBlockByrefVariable should be reformulated in terms of complex
// addresses instead.
if (Ty->isBlockByrefStruct()) {
@@ -221,18 +232,55 @@ const DIType *DbgVariable::getType() const {
uint16_t tag = Ty->getTag();
if (tag == dwarf::DW_TAG_pointer_type)
- subType = resolve(cast<DIDerivedType>(Ty)->getBaseType());
+ subType = cast<DIDerivedType>(Ty)->getBaseType();
auto Elements = cast<DICompositeType>(subType)->getElements();
for (unsigned i = 0, N = Elements.size(); i < N; ++i) {
auto *DT = cast<DIDerivedType>(Elements[i]);
if (getName() == DT->getName())
- return resolve(DT->getBaseType());
+ return DT->getBaseType();
}
}
return Ty;
}
+/// Get .debug_loc entry for the instruction range starting at MI.
+static DbgValueLoc getDebugLocValue(const MachineInstr *MI) {
+ const DIExpression *Expr = MI->getDebugExpression();
+ assert(MI->getNumOperands() == 4);
+ if (MI->getOperand(0).isReg()) {
+ auto RegOp = MI->getOperand(0);
+ auto Op1 = MI->getOperand(1);
+ // If the second operand is an immediate, this is a
+ // register-indirect address.
+ assert((!Op1.isImm() || (Op1.getImm() == 0)) && "unexpected offset");
+ MachineLocation MLoc(RegOp.getReg(), Op1.isImm());
+ return DbgValueLoc(Expr, MLoc);
+ }
+ if (MI->getOperand(0).isImm())
+ return DbgValueLoc(Expr, MI->getOperand(0).getImm());
+ if (MI->getOperand(0).isFPImm())
+ return DbgValueLoc(Expr, MI->getOperand(0).getFPImm());
+ if (MI->getOperand(0).isCImm())
+ return DbgValueLoc(Expr, MI->getOperand(0).getCImm());
+
+ llvm_unreachable("Unexpected 4-operand DBG_VALUE instruction!");
+}
+
+void DbgVariable::initializeDbgValue(const MachineInstr *DbgValue) {
+ assert(FrameIndexExprs.empty() && "Already initialized?");
+ assert(!ValueLoc.get() && "Already initialized?");
+
+ assert(getVariable() == DbgValue->getDebugVariable() && "Wrong variable");
+ assert(getInlinedAt() == DbgValue->getDebugLoc()->getInlinedAt() &&
+ "Wrong inlined-at");
+
+ ValueLoc = llvm::make_unique<DbgValueLoc>(getDebugLocValue(DbgValue));
+ if (auto *E = DbgValue->getDebugExpression())
+ if (E->getNumElements())
+ FrameIndexExprs.push_back({0, E});
+}
+
ArrayRef<DbgVariable::FrameIndexExpr> DbgVariable::getFrameIndexExprs() const {
if (FrameIndexExprs.size() == 1)
return FrameIndexExprs;
@@ -252,8 +300,8 @@ ArrayRef<DbgVariable::FrameIndexExpr> DbgVariable::getFrameIndexExprs() const {
}
void DbgVariable::addMMIEntry(const DbgVariable &V) {
- assert(DebugLocListIndex == ~0U && !MInsn && "not an MMI entry");
- assert(V.DebugLocListIndex == ~0U && !V.MInsn && "not an MMI entry");
+ assert(DebugLocListIndex == ~0U && !ValueLoc.get() && "not an MMI entry");
+ assert(V.DebugLocListIndex == ~0U && !V.ValueLoc.get() && "not an MMI entry");
assert(V.getVariable() == getVariable() && "conflicting variable");
assert(V.getInlinedAt() == getInlinedAt() && "conflicting inlined-at location");
@@ -315,7 +363,7 @@ DwarfDebug::DwarfDebug(AsmPrinter *A, Module *M)
IsDarwin(A->TM.getTargetTriple().isOSDarwin()) {
const Triple &TT = Asm->TM.getTargetTriple();
- // Make sure we know our "debugger tuning." The target option takes
+ // Make sure we know our "debugger tuning". The target option takes
// precedence; fall back to triple-based defaults.
if (Asm->TM.Options.DebuggerTuning != DebuggerKind::Default)
DebuggerTuning = Asm->TM.Options.DebuggerTuning;
@@ -658,6 +706,11 @@ DwarfDebug::getOrCreateDwarfCompileUnit(const DICompileUnit *DIUnit) {
NewCU.setSection(Asm->getObjFileLowering().getDwarfInfoSection());
}
+ // Create DIEs for function declarations used for call site debug info.
+ for (auto Scope : DIUnit->getRetainedTypes())
+ if (auto *SP = dyn_cast_or_null<DISubprogram>(Scope))
+ NewCU.getOrCreateSubprogramDIE(SP);
+
CUMap.insert({DIUnit, &NewCU});
CUDieMap.insert({&NewCU.getUnitDie(), &NewCU});
return NewCU;
@@ -890,13 +943,6 @@ void DwarfDebug::finalizeModuleInfo() {
// ranges for all subprogram DIEs for mach-o.
DwarfCompileUnit &U = SkCU ? *SkCU : TheCU;
- // We don't keep track of which addresses are used in which CU so this
- // is a bit pessimistic under LTO.
- if (!AddrPool.isEmpty() &&
- (getDwarfVersion() >= 5 ||
- (SkCU && !empty(TheCU.getUnitDie().children()))))
- U.addAddrTableBase();
-
if (unsigned NumRanges = TheCU.getRanges().size()) {
if (NumRanges > 1 && useRangesSection())
// A DW_AT_low_pc attribute may also be specified in combination with
@@ -909,6 +955,13 @@ void DwarfDebug::finalizeModuleInfo() {
U.attachRangesOrLowHighPC(U.getUnitDie(), TheCU.takeRanges());
}
+ // We don't keep track of which addresses are used in which CU so this
+ // is a bit pessimistic under LTO.
+ if (!AddrPool.isEmpty() &&
+ (getDwarfVersion() >= 5 ||
+ (SkCU && !empty(TheCU.getUnitDie().children()))))
+ U.addAddrTableBase();
+
if (getDwarfVersion() >= 5) {
if (U.hasRangeLists())
U.addRnglistsBase();
@@ -941,6 +994,11 @@ void DwarfDebug::endModule() {
assert(CurFn == nullptr);
assert(CurMI == nullptr);
+ for (const auto &P : CUMap) {
+ auto &CU = *P.second;
+ CU.createBaseTypeDIEs();
+ }
+
// If we aren't actually generating debug info (check beginModule -
// conditionalized on !DisableDebugInfoPrinting and the presence of the
// llvm.dbg.cu metadata node)
@@ -1059,161 +1117,177 @@ void DwarfDebug::collectVariableInfoFromMFTable(
}
}
-// Get .debug_loc entry for the instruction range starting at MI.
-static DebugLocEntry::Value getDebugLocValue(const MachineInstr *MI) {
- const DIExpression *Expr = MI->getDebugExpression();
- assert(MI->getNumOperands() == 4);
- if (MI->getOperand(0).isReg()) {
- auto RegOp = MI->getOperand(0);
- auto Op1 = MI->getOperand(1);
- // If the second operand is an immediate, this is a
- // register-indirect address.
- assert((!Op1.isImm() || (Op1.getImm() == 0)) && "unexpected offset");
- MachineLocation MLoc(RegOp.getReg(), Op1.isImm());
- return DebugLocEntry::Value(Expr, MLoc);
- }
- if (MI->getOperand(0).isImm())
- return DebugLocEntry::Value(Expr, MI->getOperand(0).getImm());
- if (MI->getOperand(0).isFPImm())
- return DebugLocEntry::Value(Expr, MI->getOperand(0).getFPImm());
- if (MI->getOperand(0).isCImm())
- return DebugLocEntry::Value(Expr, MI->getOperand(0).getCImm());
-
- llvm_unreachable("Unexpected 4-operand DBG_VALUE instruction!");
-}
+/// Determine whether a *singular* DBG_VALUE is valid for the entirety of its
+/// enclosing lexical scope. The check ensures there are no other instructions
+/// in the same lexical scope preceding the DBG_VALUE and that its range is
+/// either open or otherwise rolls off the end of the scope.
+static bool validThroughout(LexicalScopes &LScopes,
+ const MachineInstr *DbgValue,
+ const MachineInstr *RangeEnd) {
+ assert(DbgValue->getDebugLoc() && "DBG_VALUE without a debug location");
+ auto MBB = DbgValue->getParent();
+ auto DL = DbgValue->getDebugLoc();
+ auto *LScope = LScopes.findLexicalScope(DL);
+ // Scope doesn't exist; this is a dead DBG_VALUE.
+ if (!LScope)
+ return false;
+ auto &LSRange = LScope->getRanges();
+ if (LSRange.size() == 0)
+ return false;
-/// 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.
-bool DebugLocEntry::MergeValues(const DebugLocEntry &Next) {
- if (Begin == Next.Begin) {
- auto *FirstExpr = cast<DIExpression>(Values[0].Expression);
- auto *FirstNextExpr = cast<DIExpression>(Next.Values[0].Expression);
- if (!FirstExpr->isFragment() || !FirstNextExpr->isFragment())
+ // Determine if the DBG_VALUE is valid at the beginning of its lexical block.
+ const MachineInstr *LScopeBegin = LSRange.front().first;
+ // Early exit if the lexical scope begins outside of the current block.
+ if (LScopeBegin->getParent() != MBB)
+ return false;
+ MachineBasicBlock::const_reverse_iterator Pred(DbgValue);
+ for (++Pred; Pred != MBB->rend(); ++Pred) {
+ if (Pred->getFlag(MachineInstr::FrameSetup))
+ break;
+ auto PredDL = Pred->getDebugLoc();
+ if (!PredDL || Pred->isMetaInstruction())
+ continue;
+ // Check whether the instruction preceding the DBG_VALUE is in the same
+ // (sub)scope as the DBG_VALUE.
+ if (DL->getScope() == PredDL->getScope())
+ return false;
+ auto *PredScope = LScopes.findLexicalScope(PredDL);
+ if (!PredScope || LScope->dominates(PredScope))
return false;
+ }
- // We can only merge entries if none of the fragments overlap any others.
- // In doing so, we can take advantage of the fact that both lists are
- // sorted.
- for (unsigned i = 0, j = 0; i < Values.size(); ++i) {
- for (; j < Next.Values.size(); ++j) {
- 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;
- // Values[i] is entirely before Next.Values[j],
- // so go back to the next entry of Values.
- else if (res == -1)
- break;
- // Next.Values[j] is entirely before Values[i], so go on to the
- // next entry of Next.Values.
- }
- }
+ // If the range of the DBG_VALUE is open-ended, report success.
+ if (!RangeEnd)
+ return true;
- addValues(Next.Values);
- End = Next.End;
+ // Fail if there are instructions belonging to our scope in another block.
+ const MachineInstr *LScopeEnd = LSRange.back().second;
+ if (LScopeEnd->getParent() != MBB)
+ return false;
+
+ // Single, constant DBG_VALUEs in the prologue are promoted to be live
+ // throughout the function. This is a hack, presumably for DWARF v2 and not
+ // necessarily correct. It would be much better to use a dbg.declare instead
+ // if we know the constant is live throughout the scope.
+ if (DbgValue->getOperand(0).isImm() && MBB->pred_empty())
return true;
- }
+
return false;
}
/// Build the location list for all DBG_VALUEs in the function that
-/// describe the same variable. If the ranges of several independent
-/// fragments of the same variable overlap partially, split them up and
-/// combine the ranges. The resulting DebugLocEntries are will have
+/// describe the same variable. The resulting DebugLocEntries will have
/// strict monotonically increasing begin addresses and will never
-/// overlap.
+/// overlap. If the resulting list has only one entry that is valid
+/// throughout variable's scope return true.
+//
+// See the definition of DbgValueHistoryMap::Entry for an explanation of the
+// different kinds of history map entries. One thing to be aware of is that if
+// a debug value is ended by another entry (rather than being valid until the
+// end of the function), that entry's instruction may or may not be included in
+// the range, depending on if the entry is a clobbering entry (it has an
+// instruction that clobbers one or more preceding locations), or if it is an
+// (overlapping) debug value entry. This distinction can be seen in the example
+// below. The first debug value is ended by the clobbering entry 2, and the
+// second and third debug values are ended by the overlapping debug value entry
+// 4.
//
// Input:
//
-// Ranges History [var, loc, fragment ofs size]
-// 0 | [x, (reg0, fragment 0, 32)]
-// 1 | | [x, (reg1, fragment 32, 32)] <- IsFragmentOfPrevEntry
-// 2 | | ...
-// 3 | [clobber reg0]
-// 4 [x, (mem, fragment 0, 64)] <- overlapping with both previous fragments of
-// x.
+// History map entries [type, end index, mi]
//
-// Output:
+// 0 | [DbgValue, 2, DBG_VALUE $reg0, [...] (fragment 0, 32)]
+// 1 | | [DbgValue, 4, DBG_VALUE $reg1, [...] (fragment 32, 32)]
+// 2 | | [Clobber, $reg0 = [...], -, -]
+// 3 | | [DbgValue, 4, DBG_VALUE 123, [...] (fragment 64, 32)]
+// 4 [DbgValue, ~0, DBG_VALUE @g, [...] (fragment 0, 96)]
//
-// [0-1] [x, (reg0, fragment 0, 32)]
-// [1-3] [x, (reg0, fragment 0, 32), (reg1, fragment 32, 32)]
-// [3-4] [x, (reg1, fragment 32, 32)]
-// [4- ] [x, (mem, fragment 0, 64)]
-void
-DwarfDebug::buildLocationList(SmallVectorImpl<DebugLocEntry> &DebugLoc,
- const DbgValueHistoryMap::InstrRanges &Ranges) {
- SmallVector<DebugLocEntry::Value, 4> OpenRanges;
-
- for (auto I = Ranges.begin(), E = Ranges.end(); I != E; ++I) {
- const MachineInstr *Begin = I->first;
- const MachineInstr *End = I->second;
- assert(Begin->isDebugValue() && "Invalid History entry");
-
- // Check if a variable is inaccessible in this range.
- if (Begin->getNumOperands() > 1 &&
- Begin->getOperand(0).isReg() && !Begin->getOperand(0).getReg()) {
- OpenRanges.clear();
- continue;
- }
-
- // If this fragment overlaps with any open ranges, truncate them.
- const DIExpression *DIExpr = Begin->getDebugExpression();
- auto Last = remove_if(OpenRanges, [&](DebugLocEntry::Value R) {
- return DIExpr->fragmentsOverlap(R.getExpression());
- });
+// Output [start, end) [Value...]:
+//
+// [0-1) [(reg0, fragment 0, 32)]
+// [1-3) [(reg0, fragment 0, 32), (reg1, fragment 32, 32)]
+// [3-4) [(reg1, fragment 32, 32), (123, fragment 64, 32)]
+// [4-) [(@g, fragment 0, 96)]
+bool DwarfDebug::buildLocationList(SmallVectorImpl<DebugLocEntry> &DebugLoc,
+ const DbgValueHistoryMap::Entries &Entries) {
+ using OpenRange =
+ std::pair<DbgValueHistoryMap::EntryIndex, DbgValueLoc>;
+ SmallVector<OpenRange, 4> OpenRanges;
+ bool isSafeForSingleLocation = true;
+ const MachineInstr *StartDebugMI = nullptr;
+ const MachineInstr *EndMI = nullptr;
+
+ for (auto EB = Entries.begin(), EI = EB, EE = Entries.end(); EI != EE; ++EI) {
+ const MachineInstr *Instr = EI->getInstr();
+
+ // Remove all values that are no longer live.
+ size_t Index = std::distance(EB, EI);
+ auto Last =
+ remove_if(OpenRanges, [&](OpenRange &R) { return R.first <= Index; });
OpenRanges.erase(Last, OpenRanges.end());
- const MCSymbol *StartLabel = getLabelBeforeInsn(Begin);
- assert(StartLabel && "Forgot label before DBG_VALUE starting a range!");
+ // If we are dealing with a clobbering entry, this iteration will result in
+ // a location list entry starting after the clobbering instruction.
+ const MCSymbol *StartLabel =
+ EI->isClobber() ? getLabelAfterInsn(Instr) : getLabelBeforeInsn(Instr);
+ assert(StartLabel &&
+ "Forgot label before/after instruction starting a range!");
const MCSymbol *EndLabel;
- if (End != nullptr)
- EndLabel = getLabelAfterInsn(End);
- else if (std::next(I) == Ranges.end())
+ if (std::next(EI) == Entries.end()) {
EndLabel = Asm->getFunctionEnd();
+ if (EI->isClobber())
+ EndMI = EI->getInstr();
+ }
+ else if (std::next(EI)->isClobber())
+ EndLabel = getLabelAfterInsn(std::next(EI)->getInstr());
else
- EndLabel = getLabelBeforeInsn(std::next(I)->first);
+ EndLabel = getLabelBeforeInsn(std::next(EI)->getInstr());
assert(EndLabel && "Forgot label after instruction ending a range!");
- LLVM_DEBUG(dbgs() << "DotDebugLoc: " << *Begin << "\n");
+ if (EI->isDbgValue())
+ LLVM_DEBUG(dbgs() << "DotDebugLoc: " << *Instr << "\n");
+
+ // If this history map entry has a debug value, add that to the list of
+ // open ranges and check if its location is valid for a single value
+ // location.
+ if (EI->isDbgValue()) {
+ // Do not add undef debug values, as they are redundant information in
+ // the location list entries. An undef debug results in an empty location
+ // description. If there are any non-undef fragments then padding pieces
+ // with empty location descriptions will automatically be inserted, and if
+ // all fragments are undef then the whole location list entry is
+ // redundant.
+ if (!Instr->isUndefDebugValue()) {
+ auto Value = getDebugLocValue(Instr);
+ OpenRanges.emplace_back(EI->getEndIndex(), Value);
+
+ // TODO: Add support for single value fragment locations.
+ if (Instr->getDebugExpression()->isFragment())
+ isSafeForSingleLocation = false;
+
+ if (!StartDebugMI)
+ StartDebugMI = Instr;
+ } else {
+ isSafeForSingleLocation = false;
+ }
+ }
- auto Value = getDebugLocValue(Begin);
+ // Location list entries with empty location descriptions are redundant
+ // information in DWARF, so do not emit those.
+ if (OpenRanges.empty())
+ continue;
// Omit entries with empty ranges as they do not have any effect in DWARF.
if (StartLabel == EndLabel) {
- // If this is a fragment, we must still add the value to the list of
- // open ranges, since it may describe non-overlapping parts of the
- // variable.
- if (DIExpr->isFragment())
- OpenRanges.push_back(Value);
LLVM_DEBUG(dbgs() << "Omitting location list entry with empty range.\n");
continue;
}
- DebugLocEntry Loc(StartLabel, EndLabel, Value);
- bool couldMerge = false;
-
- // If this is a fragment, it may belong to the current DebugLocEntry.
- if (DIExpr->isFragment()) {
- // Add this value to the list of open ranges.
- OpenRanges.push_back(Value);
-
- // Attempt to add the fragment to the last entry.
- if (!DebugLoc.empty())
- if (DebugLoc.back().MergeValues(Loc))
- couldMerge = true;
- }
-
- if (!couldMerge) {
- // Need to add a new DebugLocEntry. Add all values from still
- // valid non-overlapping fragments.
- if (OpenRanges.size())
- Loc.addValues(OpenRanges);
-
- DebugLoc.push_back(std::move(Loc));
- }
+ SmallVector<DbgValueLoc, 4> Values;
+ for (auto &R : OpenRanges)
+ Values.push_back(R.second);
+ DebugLoc.emplace_back(StartLabel, EndLabel, Values);
// Attempt to coalesce the ranges of two otherwise identical
// DebugLocEntries.
@@ -1229,6 +1303,9 @@ DwarfDebug::buildLocationList(SmallVectorImpl<DebugLocEntry> &DebugLoc,
if (PrevEntry != DebugLoc.rend() && PrevEntry->MergeRanges(*CurEntry))
DebugLoc.pop_back();
}
+
+ return DebugLoc.size() == 1 && isSafeForSingleLocation &&
+ validThroughout(LScopes, StartDebugMI, EndMI);
}
DbgEntity *DwarfDebug::createConcreteEntity(DwarfCompileUnit &TheCU,
@@ -1253,64 +1330,6 @@ DbgEntity *DwarfDebug::createConcreteEntity(DwarfCompileUnit &TheCU,
return ConcreteEntities.back().get();
}
-/// Determine whether a *singular* DBG_VALUE is valid for the entirety of its
-/// enclosing lexical scope. The check ensures there are no other instructions
-/// in the same lexical scope preceding the DBG_VALUE and that its range is
-/// either open or otherwise rolls off the end of the scope.
-static bool validThroughout(LexicalScopes &LScopes,
- const MachineInstr *DbgValue,
- const MachineInstr *RangeEnd) {
- assert(DbgValue->getDebugLoc() && "DBG_VALUE without a debug location");
- auto MBB = DbgValue->getParent();
- auto DL = DbgValue->getDebugLoc();
- auto *LScope = LScopes.findLexicalScope(DL);
- // Scope doesn't exist; this is a dead DBG_VALUE.
- if (!LScope)
- return false;
- auto &LSRange = LScope->getRanges();
- if (LSRange.size() == 0)
- return false;
-
- // Determine if the DBG_VALUE is valid at the beginning of its lexical block.
- const MachineInstr *LScopeBegin = LSRange.front().first;
- // Early exit if the lexical scope begins outside of the current block.
- if (LScopeBegin->getParent() != MBB)
- return false;
- MachineBasicBlock::const_reverse_iterator Pred(DbgValue);
- for (++Pred; Pred != MBB->rend(); ++Pred) {
- if (Pred->getFlag(MachineInstr::FrameSetup))
- break;
- auto PredDL = Pred->getDebugLoc();
- if (!PredDL || Pred->isMetaInstruction())
- continue;
- // Check whether the instruction preceding the DBG_VALUE is in the same
- // (sub)scope as the DBG_VALUE.
- if (DL->getScope() == PredDL->getScope())
- return false;
- auto *PredScope = LScopes.findLexicalScope(PredDL);
- if (!PredScope || LScope->dominates(PredScope))
- return false;
- }
-
- // If the range of the DBG_VALUE is open-ended, report success.
- if (!RangeEnd)
- return true;
-
- // Fail if there are instructions belonging to our scope in another block.
- const MachineInstr *LScopeEnd = LSRange.back().second;
- if (LScopeEnd->getParent() != MBB)
- return false;
-
- // Single, constant DBG_VALUEs in the prologue are promoted to be live
- // throughout the function. This is a hack, presumably for DWARF v2 and not
- // necessarily correct. It would be much better to use a dbg.declare instead
- // if we know the constant is live throughout the scope.
- if (DbgValue->getOperand(0).isImm() && MBB->pred_empty())
- return true;
-
- return false;
-}
-
// Find variables for each lexical scope.
void DwarfDebug::collectEntityInfo(DwarfCompileUnit &TheCU,
const DISubprogram *SP,
@@ -1324,8 +1343,8 @@ void DwarfDebug::collectEntityInfo(DwarfCompileUnit &TheCU,
continue;
// Instruction ranges, specifying where IV is accessible.
- const auto &Ranges = I.second;
- if (Ranges.empty())
+ const auto &HistoryMapEntries = I.second;
+ if (HistoryMapEntries.empty())
continue;
LexicalScope *Scope = nullptr;
@@ -1342,15 +1361,24 @@ void DwarfDebug::collectEntityInfo(DwarfCompileUnit &TheCU,
DbgVariable *RegVar = cast<DbgVariable>(createConcreteEntity(TheCU,
*Scope, LocalVar, IV.second));
- const MachineInstr *MInsn = Ranges.front().first;
+ const MachineInstr *MInsn = HistoryMapEntries.front().getInstr();
assert(MInsn->isDebugValue() && "History must begin with debug value");
// Check if there is a single DBG_VALUE, valid throughout the var's scope.
- if (Ranges.size() == 1 &&
- validThroughout(LScopes, MInsn, Ranges.front().second)) {
- RegVar->initializeDbgValue(MInsn);
- continue;
+ // If the history map contains a single debug value, there may be an
+ // additional entry which clobbers the debug value.
+ size_t HistSize = HistoryMapEntries.size();
+ bool SingleValueWithClobber =
+ HistSize == 2 && HistoryMapEntries[1].isClobber();
+ if (HistSize == 1 || SingleValueWithClobber) {
+ const auto *End =
+ SingleValueWithClobber ? HistoryMapEntries[1].getInstr() : nullptr;
+ if (validThroughout(LScopes, MInsn, End)) {
+ RegVar->initializeDbgValue(MInsn);
+ continue;
+ }
}
+
// Do not emit location lists if .debug_loc secton is disabled.
if (!useLocSection())
continue;
@@ -1360,7 +1388,15 @@ void DwarfDebug::collectEntityInfo(DwarfCompileUnit &TheCU,
// Build the location list for this variable.
SmallVector<DebugLocEntry, 8> Entries;
- buildLocationList(Entries, Ranges);
+ bool isValidSingleLocation = buildLocationList(Entries, HistoryMapEntries);
+
+ // Check whether buildLocationList managed to merge all locations to one
+ // that is valid throughout the variable's scope. If so, produce single
+ // value location.
+ if (isValidSingleLocation) {
+ RegVar->initializeDbgValue(Entries[0].getValues()[0]);
+ continue;
+ }
// If the variable has a DIBasicType, extract it. Basic types cannot have
// unique identifiers, so don't bother resolving the type with the
@@ -1370,7 +1406,7 @@ void DwarfDebug::collectEntityInfo(DwarfCompileUnit &TheCU,
// Finalize the entry by lowering it into a DWARF bytestream.
for (auto &Entry : Entries)
- Entry.finalize(*Asm, List, BT);
+ Entry.finalize(*Asm, List, BT, TheCU);
}
// For each InlinedEntity collected from DBG_LABEL instructions, convert to
@@ -1489,7 +1525,7 @@ void DwarfDebug::beginInstruction(const MachineInstr *MI) {
// We have an explicit location, different from the previous location.
// Don't repeat a line-0 record, but otherwise emit the new location.
// (The new location might be an explicit line 0, which we do emit.)
- if (PrevInstLoc && DL.getLine() == 0 && LastAsmLine == 0)
+ if (DL.getLine() == 0 && LastAsmLine == 0)
return;
unsigned Flags = 0;
if (DL == PrologEndLoc) {
@@ -1521,6 +1557,46 @@ static DebugLoc findPrologueEndLoc(const MachineFunction *MF) {
return DebugLoc();
}
+/// Register a source line with debug info. Returns the unique label that was
+/// emitted and which provides correspondence to the source line list.
+static void recordSourceLine(AsmPrinter &Asm, unsigned Line, unsigned Col,
+ const MDNode *S, unsigned Flags, unsigned CUID,
+ uint16_t DwarfVersion,
+ ArrayRef<std::unique_ptr<DwarfCompileUnit>> DCUs) {
+ StringRef Fn;
+ unsigned FileNo = 1;
+ unsigned Discriminator = 0;
+ if (auto *Scope = cast_or_null<DIScope>(S)) {
+ Fn = Scope->getFilename();
+ if (Line != 0 && DwarfVersion >= 4)
+ if (auto *LBF = dyn_cast<DILexicalBlockFile>(Scope))
+ Discriminator = LBF->getDiscriminator();
+
+ FileNo = static_cast<DwarfCompileUnit &>(*DCUs[CUID])
+ .getOrCreateSourceID(Scope->getFile());
+ }
+ Asm.OutStreamer->EmitDwarfLocDirective(FileNo, Line, Col, Flags, 0,
+ Discriminator, Fn);
+}
+
+DebugLoc DwarfDebug::emitInitialLocDirective(const MachineFunction &MF,
+ unsigned CUID) {
+ // Get beginning of function.
+ if (DebugLoc PrologEndLoc = findPrologueEndLoc(&MF)) {
+ // Ensure the compile unit is created if the function is called before
+ // beginFunction().
+ (void)getOrCreateDwarfCompileUnit(
+ MF.getFunction().getSubprogram()->getUnit());
+ // We'd like to list the prologue as "not statements" but GDB behaves
+ // poorly if we do that. Revisit this with caution/GDB (7.5+) testing.
+ const DISubprogram *SP = PrologEndLoc->getInlinedAtScope()->getSubprogram();
+ ::recordSourceLine(*Asm, SP->getScopeLine(), 0, SP, DWARF2_FLAG_IS_STMT,
+ CUID, getDwarfVersion(), getUnits());
+ return PrologEndLoc;
+ }
+ return DebugLoc();
+}
+
// Gather pre-function debug information. Assumes being called immediately
// after the function entry point has been emitted.
void DwarfDebug::beginFunctionImpl(const MachineFunction *MF) {
@@ -1543,13 +1619,8 @@ void DwarfDebug::beginFunctionImpl(const MachineFunction *MF) {
Asm->OutStreamer->getContext().setDwarfCompileUnitID(CU.getUniqueID());
// Record beginning of function.
- PrologEndLoc = findPrologueEndLoc(MF);
- if (PrologEndLoc) {
- // We'd like to list the prologue as "not statements" but GDB behaves
- // poorly if we do that. Revisit this with caution/GDB (7.5+) testing.
- auto *SP = PrologEndLoc->getInlinedAtScope()->getSubprogram();
- recordSourceLine(SP->getScopeLine(), 0, SP, DWARF2_FLAG_IS_STMT);
- }
+ PrologEndLoc = emitInitialLocDirective(
+ *MF, Asm->OutStreamer->getContext().getDwarfCompileUnitID());
}
void DwarfDebug::skippedNonDebugFunction() {
@@ -1647,21 +1718,9 @@ void DwarfDebug::endFunctionImpl(const MachineFunction *MF) {
// emitted and which provides correspondence to the source line list.
void DwarfDebug::recordSourceLine(unsigned Line, unsigned Col, const MDNode *S,
unsigned Flags) {
- StringRef Fn;
- unsigned FileNo = 1;
- unsigned Discriminator = 0;
- if (auto *Scope = cast_or_null<DIScope>(S)) {
- Fn = Scope->getFilename();
- if (Line != 0 && getDwarfVersion() >= 4)
- if (auto *LBF = dyn_cast<DILexicalBlockFile>(Scope))
- Discriminator = LBF->getDiscriminator();
-
- unsigned CUID = Asm->OutStreamer->getContext().getDwarfCompileUnitID();
- FileNo = static_cast<DwarfCompileUnit &>(*InfoHolder.getUnits()[CUID])
- .getOrCreateSourceID(Scope->getFile());
- }
- Asm->OutStreamer->EmitDwarfLocDirective(FileNo, Line, Col, Flags, 0,
- Discriminator, Fn);
+ ::recordSourceLine(*Asm, Line, Col, S, Flags,
+ Asm->OutStreamer->getContext().getDwarfCompileUnitID(),
+ getDwarfVersion(), getUnits());
}
//===----------------------------------------------------------------------===//
@@ -1890,17 +1949,59 @@ void DwarfDebug::emitDebugStr() {
}
void DwarfDebug::emitDebugLocEntry(ByteStreamer &Streamer,
- const DebugLocStream::Entry &Entry) {
+ const DebugLocStream::Entry &Entry,
+ const DwarfCompileUnit *CU) {
auto &&Comments = DebugLocs.getComments(Entry);
auto Comment = Comments.begin();
auto End = Comments.end();
- for (uint8_t Byte : DebugLocs.getBytes(Entry))
- Streamer.EmitInt8(Byte, Comment != End ? *(Comment++) : "");
+
+ // The expressions are inserted into a byte stream rather early (see
+ // DwarfExpression::addExpression) so for those ops (e.g. DW_OP_convert) that
+ // need to reference a base_type DIE the offset of that DIE is not yet known.
+ // To deal with this we instead insert a placeholder early and then extract
+ // it here and replace it with the real reference.
+ unsigned PtrSize = Asm->MAI->getCodePointerSize();
+ DWARFDataExtractor Data(StringRef(DebugLocs.getBytes(Entry).data(),
+ DebugLocs.getBytes(Entry).size()),
+ Asm->getDataLayout().isLittleEndian(), PtrSize);
+ DWARFExpression Expr(Data, getDwarfVersion(), PtrSize);
+
+ using Encoding = DWARFExpression::Operation::Encoding;
+ uint32_t Offset = 0;
+ for (auto &Op : Expr) {
+ assert(Op.getCode() != dwarf::DW_OP_const_type &&
+ "3 operand ops not yet supported");
+ Streamer.EmitInt8(Op.getCode(), Comment != End ? *(Comment++) : "");
+ Offset++;
+ for (unsigned I = 0; I < 2; ++I) {
+ if (Op.getDescription().Op[I] == Encoding::SizeNA)
+ continue;
+ if (Op.getDescription().Op[I] == Encoding::BaseTypeRef) {
+ if (CU) {
+ uint64_t Offset = CU->ExprRefedBaseTypes[Op.getRawOperand(I)].Die->getOffset();
+ assert(Offset < (1ULL << (ULEB128PadSize * 7)) && "Offset wont fit");
+ Asm->EmitULEB128(Offset, nullptr, ULEB128PadSize);
+ } else {
+ // Emit a reference to the 'generic type'.
+ Asm->EmitULEB128(0, nullptr, ULEB128PadSize);
+ }
+ // Make sure comments stay aligned.
+ for (unsigned J = 0; J < ULEB128PadSize; ++J)
+ if (Comment != End)
+ Comment++;
+ } else {
+ for (uint32_t J = Offset; J < Op.getOperandEndOffset(I); ++J)
+ Streamer.EmitInt8(Data.getData()[J], Comment != End ? *(Comment++) : "");
+ }
+ Offset = Op.getOperandEndOffset(I);
+ }
+ assert(Offset == Op.getEndOffset());
+ }
}
-static void emitDebugLocValue(const AsmPrinter &AP, const DIBasicType *BT,
- const DebugLocEntry::Value &Value,
- DwarfExpression &DwarfExpr) {
+void DwarfDebug::emitDebugLocValue(const AsmPrinter &AP, const DIBasicType *BT,
+ const DbgValueLoc &Value,
+ DwarfExpression &DwarfExpr) {
auto *DIExpr = Value.getExpression();
DIExpressionCursor ExprCursor(DIExpr);
DwarfExpr.addFragmentOffset(DIExpr);
@@ -1916,6 +2017,12 @@ static void emitDebugLocValue(const AsmPrinter &AP, const DIBasicType *BT,
if (Location.isIndirect())
DwarfExpr.setMemoryLocationKind();
DIExpressionCursor Cursor(DIExpr);
+
+ if (DIExpr->isEntryValue()) {
+ DwarfExpr.setEntryValueFlag();
+ DwarfExpr.addEntryValueExpression(Cursor);
+ }
+
const TargetRegisterInfo &TRI = *AP.MF->getSubtarget().getRegisterInfo();
if (!DwarfExpr.addMachineRegExpression(TRI, Cursor, Location.getReg()))
return;
@@ -1929,38 +2036,50 @@ static void emitDebugLocValue(const AsmPrinter &AP, const DIBasicType *BT,
void DebugLocEntry::finalize(const AsmPrinter &AP,
DebugLocStream::ListBuilder &List,
- const DIBasicType *BT) {
+ const DIBasicType *BT,
+ DwarfCompileUnit &TheCU) {
+ assert(!Values.empty() &&
+ "location list entries without values are redundant");
assert(Begin != End && "unexpected location list entry with empty range");
DebugLocStream::EntryBuilder Entry(List, Begin, End);
BufferByteStreamer Streamer = Entry.getStreamer();
- DebugLocDwarfExpression DwarfExpr(AP.getDwarfVersion(), Streamer);
- const DebugLocEntry::Value &Value = Values[0];
+ DebugLocDwarfExpression DwarfExpr(AP.getDwarfVersion(), Streamer, TheCU);
+ const DbgValueLoc &Value = Values[0];
if (Value.isFragment()) {
// Emit all fragments that belong to the same variable and range.
- assert(llvm::all_of(Values, [](DebugLocEntry::Value P) {
+ assert(llvm::all_of(Values, [](DbgValueLoc P) {
return P.isFragment();
}) && "all values are expected to be fragments");
assert(std::is_sorted(Values.begin(), Values.end()) &&
"fragments are expected to be sorted");
for (auto Fragment : Values)
- emitDebugLocValue(AP, BT, Fragment, DwarfExpr);
+ DwarfDebug::emitDebugLocValue(AP, BT, Fragment, DwarfExpr);
} else {
assert(Values.size() == 1 && "only fragments may have >1 value");
- emitDebugLocValue(AP, BT, Value, DwarfExpr);
+ DwarfDebug::emitDebugLocValue(AP, BT, Value, DwarfExpr);
}
DwarfExpr.finalize();
}
-void DwarfDebug::emitDebugLocEntryLocation(const DebugLocStream::Entry &Entry) {
+void DwarfDebug::emitDebugLocEntryLocation(const DebugLocStream::Entry &Entry,
+ const DwarfCompileUnit *CU) {
// Emit the size.
Asm->OutStreamer->AddComment("Loc expr size");
- Asm->emitInt16(DebugLocs.getBytes(Entry).size());
-
+ if (getDwarfVersion() >= 5)
+ Asm->EmitULEB128(DebugLocs.getBytes(Entry).size());
+ else if (DebugLocs.getBytes(Entry).size() <= std::numeric_limits<uint16_t>::max())
+ Asm->emitInt16(DebugLocs.getBytes(Entry).size());
+ else {
+ // The entry is too big to fit into 16 bit, drop it as there is nothing we
+ // can do.
+ Asm->emitInt16(0);
+ return;
+ }
// Emit the entry.
APByteStreamer Streamer(*Asm);
- emitDebugLocEntry(Streamer, Entry);
+ emitDebugLocEntry(Streamer, Entry, CU);
}
// Emit the common part of the DWARF 5 range/locations list tables header.
@@ -2060,7 +2179,7 @@ void DwarfDebug::emitDebugLoc() {
Asm->EmitLabelDifference(Entry.EndSym, Base, Size);
}
- emitDebugLocEntryLocation(Entry);
+ emitDebugLocEntryLocation(Entry, CU);
continue;
}
@@ -2081,7 +2200,7 @@ void DwarfDebug::emitDebugLoc() {
Asm->OutStreamer->EmitSymbolValue(Entry.EndSym, Size);
}
- emitDebugLocEntryLocation(Entry);
+ emitDebugLocEntryLocation(Entry, CU);
}
if (IsLocLists) {
@@ -2100,9 +2219,9 @@ void DwarfDebug::emitDebugLoc() {
}
void DwarfDebug::emitDebugLocDWO() {
- Asm->OutStreamer->SwitchSection(
- Asm->getObjFileLowering().getDwarfLocDWOSection());
for (const auto &List : DebugLocs.getLists()) {
+ Asm->OutStreamer->SwitchSection(
+ Asm->getObjFileLowering().getDwarfLocDWOSection());
Asm->OutStreamer->EmitLabel(List.Label);
for (const auto &Entry : DebugLocs.getEntries(List)) {
// GDB only supports startx_length in pre-standard split-DWARF.
@@ -2117,7 +2236,7 @@ void DwarfDebug::emitDebugLocDWO() {
Asm->EmitULEB128(idx);
Asm->EmitLabelDifference(Entry.EndSym, Entry.BeginSym, 4);
- emitDebugLocEntryLocation(Entry);
+ emitDebugLocEntryLocation(Entry, List.CU);
}
Asm->emitInt8(dwarf::DW_LLE_end_of_list);
}
@@ -2170,19 +2289,18 @@ void DwarfDebug::emitDebugARanges() {
}
// Sort the symbols by offset within the section.
- 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;
-
- // Symbols with no order assigned should be placed at the end.
- // (e.g. section end labels)
- if (IA == 0)
- return false;
- if (IB == 0)
- return true;
- return IA < IB;
- });
+ llvm::stable_sort(List, [&](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;
+
+ // Symbols with no order assigned should be placed at the end.
+ // (e.g. section end labels)
+ if (IA == 0)
+ return false;
+ if (IB == 0)
+ return true;
+ return IA < IB;
+ });
// Insert a final terminator.
List.push_back(SymbolCU(nullptr, Asm->OutStreamer->endSection(Section)));
@@ -2687,6 +2805,22 @@ void DwarfDebug::addDwarfTypeUnitType(DwarfCompileUnit &CU,
CU.addDIETypeSignature(RefDie, Signature);
}
+DwarfDebug::NonTypeUnitContext::NonTypeUnitContext(DwarfDebug *DD)
+ : DD(DD),
+ TypeUnitsUnderConstruction(std::move(DD->TypeUnitsUnderConstruction)) {
+ DD->TypeUnitsUnderConstruction.clear();
+ assert(TypeUnitsUnderConstruction.empty() || !DD->AddrPool.hasBeenUsed());
+}
+
+DwarfDebug::NonTypeUnitContext::~NonTypeUnitContext() {
+ DD->TypeUnitsUnderConstruction = std::move(TypeUnitsUnderConstruction);
+ DD->AddrPool.resetUsedFlag();
+}
+
+DwarfDebug::NonTypeUnitContext DwarfDebug::enterNonTypeUnitContext() {
+ return NonTypeUnitContext(this);
+}
+
// 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
@@ -2699,7 +2833,7 @@ void DwarfDebug::addAccelNameImpl(const DICompileUnit &CU,
return;
if (getAccelTableKind() != AccelTableKind::Apple &&
- CU.getNameTableKind() == DICompileUnit::DebugNameTableKind::None)
+ CU.getNameTableKind() != DICompileUnit::DebugNameTableKind::Default)
return;
DwarfFile &Holder = useSplitDwarf() ? SkeletonHolder : InfoHolder;
diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.h b/lib/CodeGen/AsmPrinter/DwarfDebug.h
index 8a31e989b289..3ac474e2bdda 100644
--- a/lib/CodeGen/AsmPrinter/DwarfDebug.h
+++ b/lib/CodeGen/AsmPrinter/DwarfDebug.h
@@ -1,9 +1,8 @@
//===- llvm/CodeGen/DwarfDebug.h - Dwarf Debug Framework --------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -16,6 +15,7 @@
#include "AddressPool.h"
#include "DebugLocStream.h"
+#include "DebugLocEntry.h"
#include "DwarfFile.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
@@ -52,6 +52,7 @@ class ByteStreamer;
class DebugLocEntry;
class DIE;
class DwarfCompileUnit;
+class DwarfExpression;
class DwarfTypeUnit;
class DwarfUnit;
class LexicalScope;
@@ -111,12 +112,14 @@ public:
///
/// Variables can be created from \c DBG_VALUE instructions. Those whose
/// location changes over time use \a DebugLocListIndex, while those with a
-/// single instruction use \a MInsn and (optionally) a single entry of \a Expr.
+/// single location use \a ValueLoc and (optionally) a single entry of \a Expr.
///
/// Variables that have been optimized out use none of these fields.
class DbgVariable : public DbgEntity {
- unsigned DebugLocListIndex = ~0u; /// Offset in DebugLocs.
- const MachineInstr *MInsn = nullptr; /// DBG_VALUE instruction.
+ /// Offset in DebugLocs.
+ unsigned DebugLocListIndex = ~0u;
+ /// Single value location description.
+ std::unique_ptr<DbgValueLoc> ValueLoc = nullptr;
struct FrameIndexExpr {
int FI;
@@ -136,7 +139,7 @@ public:
/// Initialize from the MMI table.
void initializeMMI(const DIExpression *E, int FI) {
assert(FrameIndexExprs.empty() && "Already initialized?");
- assert(!MInsn && "Already initialized?");
+ assert(!ValueLoc.get() && "Already initialized?");
assert((!E || E->isValid()) && "Expected valid expression");
assert(FI != std::numeric_limits<int>::max() && "Expected valid index");
@@ -144,35 +147,35 @@ public:
FrameIndexExprs.push_back({FI, E});
}
- /// Initialize from a DBG_VALUE instruction.
- void initializeDbgValue(const MachineInstr *DbgValue) {
+ // Initialize variable's location.
+ void initializeDbgValue(DbgValueLoc Value) {
assert(FrameIndexExprs.empty() && "Already initialized?");
- assert(!MInsn && "Already initialized?");
+ assert(!ValueLoc && "Already initialized?");
+ assert(!Value.getExpression()->isFragment() && "Fragments not supported.");
- assert(getVariable() == DbgValue->getDebugVariable() && "Wrong variable");
- assert(getInlinedAt() == DbgValue->getDebugLoc()->getInlinedAt() &&
- "Wrong inlined-at");
-
- MInsn = DbgValue;
- if (auto *E = DbgValue->getDebugExpression())
+ ValueLoc = llvm::make_unique<DbgValueLoc>(Value);
+ if (auto *E = ValueLoc->getExpression())
if (E->getNumElements())
FrameIndexExprs.push_back({0, E});
}
+ /// Initialize from a DBG_VALUE instruction.
+ void initializeDbgValue(const MachineInstr *DbgValue);
+
// Accessors.
const DILocalVariable *getVariable() const {
return cast<DILocalVariable>(getEntity());
}
const DIExpression *getSingleExpression() const {
- assert(MInsn && FrameIndexExprs.size() <= 1);
+ assert(ValueLoc.get() && FrameIndexExprs.size() <= 1);
return FrameIndexExprs.size() ? FrameIndexExprs[0].Expr : nullptr;
}
void setDebugLocListIndex(unsigned O) { DebugLocListIndex = O; }
unsigned getDebugLocListIndex() const { return DebugLocListIndex; }
StringRef getName() const { return getVariable()->getName(); }
- const MachineInstr *getMInsn() const { return MInsn; }
+ const DbgValueLoc *getValueLoc() const { return ValueLoc.get(); }
/// Get the FI entries, sorted by fragment offset.
ArrayRef<FrameIndexExpr> getFrameIndexExprs() const;
bool hasFrameIndexExprs() const { return !FrameIndexExprs.empty(); }
@@ -205,7 +208,7 @@ public:
}
bool hasComplexAddress() const {
- assert(MInsn && "Expected DBG_VALUE, not MMI variable");
+ assert(ValueLoc.get() && "Expected DBG_VALUE, not MMI variable");
assert((FrameIndexExprs.empty() ||
(FrameIndexExprs.size() == 1 &&
FrameIndexExprs[0].Expr->getNumElements())) &&
@@ -219,11 +222,6 @@ public:
static bool classof(const DbgEntity *N) {
return N->getDbgEntityID() == DbgVariableKind;
}
-
-private:
- template <typename T> T *resolve(TypedDINodeRef<T> Ref) const {
- return Ref.resolve();
- }
};
//===----------------------------------------------------------------------===//
@@ -254,11 +252,6 @@ public:
static bool classof(const DbgEntity *N) {
return N->getDbgEntityID() == DbgLabelKind;
}
-
-private:
- template <typename T> T *resolve(TypedDINodeRef<T> Ref) const {
- return Ref.resolve();
- }
};
/// Helper used to pair up a symbol and its DWARF compile unit.
@@ -558,9 +551,11 @@ class DwarfDebug : public DebugHandlerBase {
DenseSet<InlinedEntity> &ProcessedVars);
/// Build the location list for all DBG_VALUEs in the
- /// function that describe the same variable.
- void buildLocationList(SmallVectorImpl<DebugLocEntry> &DebugLoc,
- const DbgValueHistoryMap::InstrRanges &Ranges);
+ /// function that describe the same variable. If the resulting
+ /// list has only one entry that is valid for entire variable's
+ /// scope return true.
+ bool buildLocationList(SmallVectorImpl<DebugLocEntry> &DebugLoc,
+ const DbgValueHistoryMap::Entries &Entries);
/// Collect variable information from the side table maintained by MF.
void collectVariableInfoFromMFTable(DwarfCompileUnit &TheCU,
@@ -593,6 +588,9 @@ public:
/// Emit all Dwarf sections that should come after the content.
void endModule() override;
+ /// Emits inital debug location directive.
+ DebugLoc emitInitialLocDirective(const MachineFunction &MF, unsigned CUID);
+
/// Process beginning of an instruction.
void beginInstruction(const MachineInstr *MI) override;
@@ -604,6 +602,19 @@ public:
void addDwarfTypeUnitType(DwarfCompileUnit &CU, StringRef Identifier,
DIE &Die, const DICompositeType *CTy);
+ friend class NonTypeUnitContext;
+ class NonTypeUnitContext {
+ DwarfDebug *DD;
+ decltype(DwarfDebug::TypeUnitsUnderConstruction) TypeUnitsUnderConstruction;
+ friend class DwarfDebug;
+ NonTypeUnitContext(DwarfDebug *DD);
+ public:
+ NonTypeUnitContext(NonTypeUnitContext&&) = default;
+ ~NonTypeUnitContext();
+ };
+
+ NonTypeUnitContext enterNonTypeUnitContext();
+
/// Add a label so that arange data can be generated for it.
void addArangeLabel(SymbolCU SCU) { ArangeLabels.push_back(SCU); }
@@ -680,15 +691,12 @@ public:
/// Emit an entry for the debug loc section. This can be used to
/// handle an entry that's going to be emitted into the debug loc section.
void emitDebugLocEntry(ByteStreamer &Streamer,
- const DebugLocStream::Entry &Entry);
+ const DebugLocStream::Entry &Entry,
+ const DwarfCompileUnit *CU);
/// Emit the location for a debug loc entry, including the size header.
- void emitDebugLocEntryLocation(const DebugLocStream::Entry &Entry);
-
- /// Find the MDNode for the given reference.
- template <typename T> T *resolve(TypedDINodeRef<T> Ref) const {
- return Ref.resolve();
- }
+ void emitDebugLocEntryLocation(const DebugLocStream::Entry &Entry,
+ const DwarfCompileUnit *CU);
void addSubprogramNames(const DICompileUnit &CU, const DISubprogram *SP,
DIE &Die);
@@ -728,6 +736,10 @@ public:
void addSectionLabel(const MCSymbol *Sym);
const MCSymbol *getSectionLabel(const MCSection *S);
+
+ static void emitDebugLocValue(const AsmPrinter &AP, const DIBasicType *BT,
+ const DbgValueLoc &Value,
+ DwarfExpression &DwarfExpr);
};
} // end namespace llvm
diff --git a/lib/CodeGen/AsmPrinter/DwarfException.h b/lib/CodeGen/AsmPrinter/DwarfException.h
index b57ea8fc6322..24bbf58b91ec 100644
--- a/lib/CodeGen/AsmPrinter/DwarfException.h
+++ b/lib/CodeGen/AsmPrinter/DwarfException.h
@@ -1,9 +1,8 @@
//===-- DwarfException.h - Dwarf Exception Framework -----------*- C++ -*--===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
diff --git a/lib/CodeGen/AsmPrinter/DwarfExpression.cpp b/lib/CodeGen/AsmPrinter/DwarfExpression.cpp
index 19c350afbf17..2858afaa1cf1 100644
--- a/lib/CodeGen/AsmPrinter/DwarfExpression.cpp
+++ b/lib/CodeGen/AsmPrinter/DwarfExpression.cpp
@@ -1,9 +1,8 @@
//===- llvm/CodeGen/DwarfExpression.cpp - Dwarf Debug Framework -----------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -12,6 +11,7 @@
//===----------------------------------------------------------------------===//
#include "DwarfExpression.h"
+#include "DwarfCompileUnit.h"
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/SmallBitVector.h"
#include "llvm/BinaryFormat/Dwarf.h"
@@ -40,7 +40,7 @@ void DwarfExpression::emitConstu(uint64_t Value) {
void DwarfExpression::addReg(int DwarfReg, const char *Comment) {
assert(DwarfReg >= 0 && "invalid negative dwarf register number");
- assert((LocationKind == Unknown || LocationKind == Register) &&
+ assert((isUnknownLocation() || isRegisterLocation()) &&
"location description already locked down");
LocationKind = Register;
if (DwarfReg < 32) {
@@ -53,7 +53,7 @@ void DwarfExpression::addReg(int DwarfReg, const char *Comment) {
void DwarfExpression::addBReg(int DwarfReg, int Offset) {
assert(DwarfReg >= 0 && "invalid negative dwarf register number");
- assert(LocationKind != Register && "location description already locked down");
+ assert(!isRegisterLocation() && "location description already locked down");
if (DwarfReg < 32) {
emitOp(dwarf::DW_OP_breg0 + DwarfReg);
} else {
@@ -184,20 +184,20 @@ void DwarfExpression::addStackValue() {
}
void DwarfExpression::addSignedConstant(int64_t Value) {
- assert(LocationKind == Implicit || LocationKind == Unknown);
+ assert(isImplicitLocation() || isUnknownLocation());
LocationKind = Implicit;
emitOp(dwarf::DW_OP_consts);
emitSigned(Value);
}
void DwarfExpression::addUnsignedConstant(uint64_t Value) {
- assert(LocationKind == Implicit || LocationKind == Unknown);
+ assert(isImplicitLocation() || isUnknownLocation());
LocationKind = Implicit;
emitConstu(Value);
}
void DwarfExpression::addUnsignedConstant(const APInt &Value) {
- assert(LocationKind == Implicit || LocationKind == Unknown);
+ assert(isImplicitLocation() || isUnknownLocation());
LocationKind = Implicit;
unsigned Size = Value.getBitWidth();
@@ -242,12 +242,16 @@ bool DwarfExpression::addMachineRegExpression(const TargetRegisterInfo &TRI,
}
// Handle simple register locations.
- if (LocationKind != Memory && !HasComplexExpression) {
+ if (!isMemoryLocation() && !HasComplexExpression) {
for (auto &Reg : DwarfRegs) {
if (Reg.DwarfRegNo >= 0)
addReg(Reg.DwarfRegNo, Reg.Comment);
addOpPiece(Reg.Size);
}
+
+ if (isEntryValue() && DwarfVersion >= 4)
+ emitOp(dwarf::DW_OP_stack_value);
+
DwarfRegs.clear();
return true;
}
@@ -296,6 +300,19 @@ bool DwarfExpression::addMachineRegExpression(const TargetRegisterInfo &TRI,
return true;
}
+void DwarfExpression::addEntryValueExpression(DIExpressionCursor &ExprCursor) {
+ auto Op = ExprCursor.take();
+ assert(Op && Op->getOp() == dwarf::DW_OP_entry_value);
+ assert(!isMemoryLocation() &&
+ "We don't support entry values of memory locations yet");
+
+ if (DwarfVersion >= 5)
+ emitOp(dwarf::DW_OP_entry_value);
+ else
+ emitOp(dwarf::DW_OP_GNU_entry_value);
+ emitUnsigned(Op->getArg(0));
+}
+
/// Assuming a well-formed expression, match "DW_OP_deref* DW_OP_LLVM_fragment?".
static bool isMemoryLocation(DIExpressionCursor ExprCursor) {
while (ExprCursor) {
@@ -319,6 +336,8 @@ void DwarfExpression::addExpression(DIExpressionCursor &&ExprCursor,
if (SubRegisterSizeInBits && N && (N->getOp() != dwarf::DW_OP_LLVM_fragment))
maskSubRegister();
+ Optional<DIExpression::ExprOperand> PrevConvertOp = None;
+
while (ExprCursor) {
auto Op = ExprCursor.take();
switch (Op->getOp()) {
@@ -341,7 +360,7 @@ void DwarfExpression::addExpression(DIExpressionCursor &&ExprCursor,
SizeInBits = std::min<unsigned>(SizeInBits, SubRegisterSizeInBits);
// Emit a DW_OP_stack_value for implicit location descriptions.
- if (LocationKind == Implicit)
+ if (isImplicitLocation())
addStackValue();
// Emit the DW_OP_piece.
@@ -352,7 +371,7 @@ void DwarfExpression::addExpression(DIExpressionCursor &&ExprCursor,
return;
}
case dwarf::DW_OP_plus_uconst:
- assert(LocationKind != Register);
+ assert(!isRegisterLocation());
emitOp(dwarf::DW_OP_plus_uconst);
emitUnsigned(Op->getArg(0));
break;
@@ -373,8 +392,8 @@ void DwarfExpression::addExpression(DIExpressionCursor &&ExprCursor,
emitOp(Op->getOp());
break;
case dwarf::DW_OP_deref:
- assert(LocationKind != Register);
- if (LocationKind != Memory && ::isMemoryLocation(ExprCursor))
+ assert(!isRegisterLocation());
+ if (!isMemoryLocation() && ::isMemoryLocation(ExprCursor))
// Turning this into a memory location description makes the deref
// implicit.
LocationKind = Memory;
@@ -382,26 +401,69 @@ void DwarfExpression::addExpression(DIExpressionCursor &&ExprCursor,
emitOp(dwarf::DW_OP_deref);
break;
case dwarf::DW_OP_constu:
- assert(LocationKind != Register);
+ assert(!isRegisterLocation());
emitConstu(Op->getArg(0));
break;
+ case dwarf::DW_OP_LLVM_convert: {
+ unsigned BitSize = Op->getArg(0);
+ dwarf::TypeKind Encoding = static_cast<dwarf::TypeKind>(Op->getArg(1));
+ if (DwarfVersion >= 5) {
+ emitOp(dwarf::DW_OP_convert);
+ // Reuse the base_type if we already have one in this CU otherwise we
+ // create a new one.
+ unsigned I = 0, E = CU.ExprRefedBaseTypes.size();
+ for (; I != E; ++I)
+ if (CU.ExprRefedBaseTypes[I].BitSize == BitSize &&
+ CU.ExprRefedBaseTypes[I].Encoding == Encoding)
+ break;
+
+ if (I == E)
+ CU.ExprRefedBaseTypes.emplace_back(BitSize, Encoding);
+
+ // If targeting a location-list; simply emit the index into the raw
+ // byte stream as ULEB128, DwarfDebug::emitDebugLocEntry has been
+ // fitted with means to extract it later.
+ // If targeting a inlined DW_AT_location; insert a DIEBaseTypeRef
+ // (containing the index and a resolve mechanism during emit) into the
+ // DIE value list.
+ emitBaseTypeRef(I);
+ } else {
+ if (PrevConvertOp && PrevConvertOp->getArg(0) < BitSize) {
+ if (Encoding == dwarf::DW_ATE_signed)
+ emitLegacySExt(PrevConvertOp->getArg(0));
+ else if (Encoding == dwarf::DW_ATE_unsigned)
+ emitLegacyZExt(PrevConvertOp->getArg(0));
+ PrevConvertOp = None;
+ } else {
+ PrevConvertOp = Op;
+ }
+ }
+ break;
+ }
case dwarf::DW_OP_stack_value:
LocationKind = Implicit;
break;
case dwarf::DW_OP_swap:
- assert(LocationKind != Register);
+ assert(!isRegisterLocation());
emitOp(dwarf::DW_OP_swap);
break;
case dwarf::DW_OP_xderef:
- assert(LocationKind != Register);
+ assert(!isRegisterLocation());
emitOp(dwarf::DW_OP_xderef);
break;
+ case dwarf::DW_OP_deref_size:
+ emitOp(dwarf::DW_OP_deref_size);
+ emitData1(Op->getArg(0));
+ break;
+ case dwarf::DW_OP_LLVM_tag_offset:
+ TagOffset = Op->getArg(0);
+ break;
default:
llvm_unreachable("unhandled opcode found in expression");
}
}
- if (LocationKind == Implicit)
+ if (isImplicitLocation())
// Turn this into an implicit location description.
addStackValue();
}
@@ -437,3 +499,25 @@ void DwarfExpression::addFragmentOffset(const DIExpression *Expr) {
addOpPiece(FragmentOffset - OffsetInBits);
OffsetInBits = FragmentOffset;
}
+
+void DwarfExpression::emitLegacySExt(unsigned FromBits) {
+ // (((X >> (FromBits - 1)) * (~0)) << FromBits) | X
+ emitOp(dwarf::DW_OP_dup);
+ emitOp(dwarf::DW_OP_constu);
+ emitUnsigned(FromBits - 1);
+ emitOp(dwarf::DW_OP_shr);
+ emitOp(dwarf::DW_OP_lit0);
+ emitOp(dwarf::DW_OP_not);
+ emitOp(dwarf::DW_OP_mul);
+ emitOp(dwarf::DW_OP_constu);
+ emitUnsigned(FromBits);
+ emitOp(dwarf::DW_OP_shl);
+ emitOp(dwarf::DW_OP_or);
+}
+
+void DwarfExpression::emitLegacyZExt(unsigned FromBits) {
+ // (X & (1 << FromBits - 1))
+ emitOp(dwarf::DW_OP_constu);
+ emitUnsigned((1ULL << FromBits) - 1);
+ emitOp(dwarf::DW_OP_and);
+}
diff --git a/lib/CodeGen/AsmPrinter/DwarfExpression.h b/lib/CodeGen/AsmPrinter/DwarfExpression.h
index 91568ba6d107..ec2ef6e575f7 100644
--- a/lib/CodeGen/AsmPrinter/DwarfExpression.h
+++ b/lib/CodeGen/AsmPrinter/DwarfExpression.h
@@ -1,9 +1,8 @@
//===- llvm/CodeGen/DwarfExpression.h - Dwarf Compile Unit ------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -28,7 +27,7 @@ namespace llvm {
class AsmPrinter;
class APInt;
class ByteStreamer;
-class DwarfUnit;
+class DwarfCompileUnit;
class DIELoc;
class TargetRegisterInfo;
@@ -105,23 +104,56 @@ protected:
const char *Comment;
};
+ DwarfCompileUnit &CU;
+
/// The register location, if any.
SmallVector<Register, 2> DwarfRegs;
/// Current Fragment Offset in Bits.
uint64_t OffsetInBits = 0;
- unsigned DwarfVersion;
/// Sometimes we need to add a DW_OP_bit_piece to describe a subregister.
- unsigned SubRegisterSizeInBits = 0;
- unsigned SubRegisterOffsetInBits = 0;
+ unsigned SubRegisterSizeInBits : 16;
+ unsigned SubRegisterOffsetInBits : 16;
/// The kind of location description being produced.
- enum { Unknown = 0, Register, Memory, Implicit } LocationKind = Unknown;
+ enum { Unknown = 0, Register, Memory, Implicit };
+
+ /// The flags of location description being produced.
+ enum { EntryValue = 1 };
+
+ unsigned LocationKind : 3;
+ unsigned LocationFlags : 2;
+ unsigned DwarfVersion : 4;
+
+public:
+ bool isUnknownLocation() const {
+ return LocationKind == Unknown;
+ }
+
+ bool isMemoryLocation() const {
+ return LocationKind == Memory;
+ }
+
+ bool isRegisterLocation() const {
+ return LocationKind == Register;
+ }
+
+ bool isImplicitLocation() const {
+ return LocationKind == Implicit;
+ }
+
+ bool isEntryValue() const {
+ return LocationFlags & EntryValue;
+ }
+ Optional<uint8_t> TagOffset;
+
+protected:
/// Push a DW_OP_piece / DW_OP_bit_piece for emitting later, if one is needed
/// to represent a subregister.
void setSubRegisterPiece(unsigned SizeInBits, unsigned OffsetInBits) {
+ assert(SizeInBits < 65536 && OffsetInBits < 65536);
SubRegisterSizeInBits = SizeInBits;
SubRegisterOffsetInBits = OffsetInBits;
}
@@ -138,6 +170,10 @@ protected:
/// Emit a raw unsigned value.
virtual void emitUnsigned(uint64_t Value) = 0;
+ virtual void emitData1(uint8_t Value) = 0;
+
+ virtual void emitBaseTypeRef(uint64_t Idx) = 0;
+
/// Emit a normalized unsigned constant.
void emitConstu(uint64_t Value);
@@ -200,7 +236,10 @@ protected:
~DwarfExpression() = default;
public:
- DwarfExpression(unsigned DwarfVersion) : DwarfVersion(DwarfVersion) {}
+ DwarfExpression(unsigned DwarfVersion, DwarfCompileUnit &CU)
+ : CU(CU), SubRegisterSizeInBits(0), SubRegisterOffsetInBits(0),
+ LocationKind(Unknown), LocationFlags(Unknown),
+ DwarfVersion(DwarfVersion) {}
/// This needs to be called last to commit any pending changes.
void finalize();
@@ -214,15 +253,17 @@ 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);
+ assert(isUnknownLocation());
LocationKind = Memory;
}
+ /// Lock this down to become an entry value location.
+ void setEntryValueFlag() {
+ LocationFlags |= EntryValue;
+ }
+
/// Emit a machine register location. As an optimization this may also consume
/// the prefix of a DwarfExpression if a more efficient representation for
/// combining the register location and the first operation exists.
@@ -237,6 +278,9 @@ public:
DIExpressionCursor &Expr, unsigned MachineReg,
unsigned FragmentOffsetInBits = 0);
+ /// Emit entry value dwarf operation.
+ void addEntryValueExpression(DIExpressionCursor &ExprCursor);
+
/// Emit all remaining operations in the DIExpressionCursor.
///
/// \param FragmentOffsetInBits If this is one fragment out of multiple
@@ -248,6 +292,9 @@ public:
/// If applicable, emit an empty DW_OP_piece / DW_OP_bit_piece to advance to
/// the fragment described by \c Expr.
void addFragmentOffset(const DIExpression *Expr);
+
+ void emitLegacySExt(unsigned FromBits);
+ void emitLegacyZExt(unsigned FromBits);
};
/// DwarfExpression implementation for .debug_loc entries.
@@ -257,27 +304,30 @@ class DebugLocDwarfExpression final : public DwarfExpression {
void emitOp(uint8_t Op, const char *Comment = nullptr) override;
void emitSigned(int64_t Value) override;
void emitUnsigned(uint64_t Value) override;
+ void emitData1(uint8_t Value) override;
+ void emitBaseTypeRef(uint64_t Idx) override;
bool isFrameRegister(const TargetRegisterInfo &TRI,
unsigned MachineReg) override;
public:
- DebugLocDwarfExpression(unsigned DwarfVersion, ByteStreamer &BS)
- : DwarfExpression(DwarfVersion), BS(BS) {}
+ DebugLocDwarfExpression(unsigned DwarfVersion, ByteStreamer &BS, DwarfCompileUnit &CU)
+ : DwarfExpression(DwarfVersion, CU), BS(BS) {}
};
/// DwarfExpression implementation for singular DW_AT_location.
class DIEDwarfExpression final : public DwarfExpression {
const AsmPrinter &AP;
- DwarfUnit &DU;
DIELoc &DIE;
void emitOp(uint8_t Op, const char *Comment = nullptr) override;
void emitSigned(int64_t Value) override;
void emitUnsigned(uint64_t Value) override;
+ void emitData1(uint8_t Value) override;
+ void emitBaseTypeRef(uint64_t Idx) override;
bool isFrameRegister(const TargetRegisterInfo &TRI,
unsigned MachineReg) override;
public:
- DIEDwarfExpression(const AsmPrinter &AP, DwarfUnit &DU, DIELoc &DIE);
+ DIEDwarfExpression(const AsmPrinter &AP, DwarfCompileUnit &CU, DIELoc &DIE);
DIELoc *finalize() {
DwarfExpression::finalize();
diff --git a/lib/CodeGen/AsmPrinter/DwarfFile.cpp b/lib/CodeGen/AsmPrinter/DwarfFile.cpp
index 78ccad481411..e3c9095d1343 100644
--- a/lib/CodeGen/AsmPrinter/DwarfFile.cpp
+++ b/lib/CodeGen/AsmPrinter/DwarfFile.cpp
@@ -1,9 +1,8 @@
//===- llvm/CodeGen/DwarfFile.cpp - Dwarf Debug Framework -----------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
@@ -44,6 +43,11 @@ void DwarfFile::emitUnit(DwarfUnit *TheU, bool UseOffsets) {
if (!S)
return;
+ // Skip CUs that ended up not being needed (split CUs that were abandoned
+ // because they added no information beyond the non-split CU)
+ if (llvm::empty(TheU->getUnitDie().values()))
+ return;
+
Asm->OutStreamer->SwitchSection(S);
TheU->emitHeader(UseOffsets);
Asm->emitDwarfDIE(TheU->getUnitDie());
@@ -63,6 +67,11 @@ void DwarfFile::computeSizeAndOffsets() {
if (TheU->getCUNode()->isDebugDirectivesOnly())
continue;
+ // Skip CUs that ended up not being needed (split CUs that were abandoned
+ // because they added no information beyond the non-split CU)
+ if (llvm::empty(TheU->getUnitDie().values()))
+ return;
+
TheU->setDebugSectionOffset(SecOffset);
SecOffset += computeSizeAndOffsetsForUnit(TheU.get());
}
diff --git a/lib/CodeGen/AsmPrinter/DwarfFile.h b/lib/CodeGen/AsmPrinter/DwarfFile.h
index 51acca8c1e53..244678ce9dc1 100644
--- a/lib/CodeGen/AsmPrinter/DwarfFile.h
+++ b/lib/CodeGen/AsmPrinter/DwarfFile.h
@@ -1,9 +1,8 @@
//===- llvm/CodeGen/DwarfFile.h - Dwarf Debug Framework ---------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
@@ -59,7 +58,6 @@ public:
MCSymbol *getSym() const { return RangeSym; }
const DwarfCompileUnit &getCU() const { return *CU; }
const SmallVectorImpl<RangeSpan> &getRanges() const { return Ranges; }
- void addRange(RangeSpan Range) { Ranges.push_back(Range); }
};
class DwarfFile {
@@ -148,7 +146,7 @@ public:
void emitUnits(bool UseOffsets);
/// Emit the given unit to its section.
- void emitUnit(DwarfUnit *U, bool UseOffsets);
+ void emitUnit(DwarfUnit *TheU, bool UseOffsets);
/// Emit a set of abbreviations to the specific section.
void emitAbbrevs(MCSection *);
diff --git a/lib/CodeGen/AsmPrinter/DwarfStringPool.cpp b/lib/CodeGen/AsmPrinter/DwarfStringPool.cpp
index 02016534a774..2a76dcb1b082 100644
--- a/lib/CodeGen/AsmPrinter/DwarfStringPool.cpp
+++ b/lib/CodeGen/AsmPrinter/DwarfStringPool.cpp
@@ -1,9 +1,8 @@
//===- llvm/CodeGen/DwarfStringPool.cpp - Dwarf Debug Framework -----------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
diff --git a/lib/CodeGen/AsmPrinter/DwarfStringPool.h b/lib/CodeGen/AsmPrinter/DwarfStringPool.h
index f484540d8d37..c5f5637fdae3 100644
--- a/lib/CodeGen/AsmPrinter/DwarfStringPool.h
+++ b/lib/CodeGen/AsmPrinter/DwarfStringPool.h
@@ -1,9 +1,8 @@
//===- llvm/CodeGen/DwarfStringPool.h - Dwarf Debug Framework ---*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
diff --git a/lib/CodeGen/AsmPrinter/DwarfUnit.cpp b/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
index 80b365f1aa43..991ab94b50ab 100644
--- a/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
+++ b/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
@@ -1,9 +1,8 @@
//===-- llvm/CodeGen/DwarfUnit.cpp - Dwarf Type and Compile Units ---------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -47,21 +46,30 @@ using namespace llvm;
#define DEBUG_TYPE "dwarfdebug"
-DIEDwarfExpression::DIEDwarfExpression(const AsmPrinter &AP, DwarfUnit &DU,
+DIEDwarfExpression::DIEDwarfExpression(const AsmPrinter &AP,
+ DwarfCompileUnit &CU,
DIELoc &DIE)
- : DwarfExpression(AP.getDwarfVersion()), AP(AP), DU(DU),
+ : DwarfExpression(AP.getDwarfVersion(), CU), AP(AP),
DIE(DIE) {}
void DIEDwarfExpression::emitOp(uint8_t Op, const char* Comment) {
- DU.addUInt(DIE, dwarf::DW_FORM_data1, Op);
+ CU.addUInt(DIE, dwarf::DW_FORM_data1, Op);
}
void DIEDwarfExpression::emitSigned(int64_t Value) {
- DU.addSInt(DIE, dwarf::DW_FORM_sdata, Value);
+ CU.addSInt(DIE, dwarf::DW_FORM_sdata, Value);
}
void DIEDwarfExpression::emitUnsigned(uint64_t Value) {
- DU.addUInt(DIE, dwarf::DW_FORM_udata, Value);
+ CU.addUInt(DIE, dwarf::DW_FORM_udata, Value);
+}
+
+void DIEDwarfExpression::emitData1(uint8_t Value) {
+ CU.addUInt(DIE, dwarf::DW_FORM_data1, Value);
+}
+
+void DIEDwarfExpression::emitBaseTypeRef(uint64_t Idx) {
+ CU.addBaseTypeRef(DIE, Idx);
}
bool DIEDwarfExpression::isFrameRegister(const TargetRegisterInfo &TRI,
@@ -285,21 +293,21 @@ void DwarfUnit::addSectionOffset(DIE &Die, dwarf::Attribute Attribute,
addUInt(Die, Attribute, dwarf::DW_FORM_data4, Integer);
}
-MD5::MD5Result *DwarfUnit::getMD5AsBytes(const DIFile *File) const {
+Optional<MD5::MD5Result> DwarfUnit::getMD5AsBytes(const DIFile *File) const {
assert(File);
if (DD->getDwarfVersion() < 5)
- return nullptr;
+ return None;
Optional<DIFile::ChecksumInfo<StringRef>> Checksum = File->getChecksum();
if (!Checksum || Checksum->Kind != DIFile::CSK_MD5)
- return nullptr;
+ return None;
// 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);
+ MD5::MD5Result CKMem;
+ std::copy(ChecksumString.begin(), ChecksumString.end(), CKMem.Bytes.data());
+ return CKMem;
}
unsigned DwarfTypeUnit::getOrCreateSourceID(const DIFile *File) {
@@ -311,7 +319,9 @@ unsigned DwarfTypeUnit::getOrCreateSourceID(const DIFile *File) {
addSectionOffset(getUnitDie(), dwarf::DW_AT_stmt_list, 0);
}
return SplitLineTable->getFile(File->getDirectory(), File->getFilename(),
- getMD5AsBytes(File), File->getSource());
+ getMD5AsBytes(File),
+ Asm->OutContext.getDwarfVersion(),
+ File->getSource());
}
void DwarfUnit::addOpAddress(DIELoc &Die, const MCSymbol *Sym) {
@@ -393,7 +403,6 @@ void DwarfUnit::addSourceLine(DIE &Die, unsigned Line, const DIFile *File) {
return;
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);
}
@@ -462,9 +471,8 @@ static bool isUnsignedDIType(DwarfDebug *DD, const DIType *Ty) {
assert(T == dwarf::DW_TAG_typedef || T == dwarf::DW_TAG_const_type ||
T == dwarf::DW_TAG_volatile_type ||
T == dwarf::DW_TAG_restrict_type || T == dwarf::DW_TAG_atomic_type);
- DITypeRef Deriv = DTy->getBaseType();
- assert(Deriv && "Expected valid base type");
- return isUnsignedDIType(DD, DD->resolve(Deriv));
+ assert(DTy->getBaseType() && "Expected valid base type");
+ return isUnsignedDIType(DD, DTy->getBaseType());
}
auto *BTy = cast<DIBasicType>(Ty);
@@ -523,6 +531,10 @@ void DwarfUnit::addConstantValue(DIE &Die, const MachineOperand &MO,
addConstantValue(Die, isUnsignedDIType(DD, Ty), MO.getImm());
}
+void DwarfUnit::addConstantValue(DIE &Die, uint64_t Val, const DIType *Ty) {
+ addConstantValue(Die, isUnsignedDIType(DD, Ty), Val);
+}
+
void DwarfUnit::addConstantValue(DIE &Die, bool Unsigned, uint64_t Val) {
// FIXME: This is a bit conservative/simple - it emits negative values always
// sign extended to 64 bits rather than minimizing the number of bytes.
@@ -603,8 +615,8 @@ DIE *DwarfUnit::getOrCreateContextDIE(const DIScope *Context) {
return getDIE(Context);
}
-DIE *DwarfTypeUnit::createTypeDIE(const DICompositeType *Ty) {
- auto *Context = resolve(Ty->getScope());
+DIE *DwarfUnit::createTypeDIE(const DICompositeType *Ty) {
+ auto *Context = Ty->getScope();
DIE *ContextDIE = getOrCreateContextDIE(Context);
if (DIE *TyDIE = getDIE(Ty))
@@ -619,6 +631,37 @@ DIE *DwarfTypeUnit::createTypeDIE(const DICompositeType *Ty) {
return &TyDIE;
}
+DIE *DwarfUnit::createTypeDIE(const DIScope *Context, DIE &ContextDIE,
+ const DIType *Ty) {
+ // Create new type.
+ DIE &TyDIE = createAndAddDIE(Ty->getTag(), ContextDIE, Ty);
+
+ updateAcceleratorTables(Context, Ty, TyDIE);
+
+ if (auto *BT = dyn_cast<DIBasicType>(Ty))
+ constructTypeDIE(TyDIE, BT);
+ else if (auto *STy = dyn_cast<DISubroutineType>(Ty))
+ constructTypeDIE(TyDIE, STy);
+ else if (auto *CTy = dyn_cast<DICompositeType>(Ty)) {
+ if (DD->generateTypeUnits() && !Ty->isForwardDecl() &&
+ (Ty->getRawName() || CTy->getRawIdentifier())) {
+ // Skip updating the accelerator tables since this is not the full type.
+ if (MDString *TypeId = CTy->getRawIdentifier())
+ DD->addDwarfTypeUnitType(getCU(), TypeId->getString(), TyDIE, CTy);
+ else {
+ auto X = DD->enterNonTypeUnitContext();
+ finishNonUnitTypeDIE(TyDIE, CTy);
+ }
+ return &TyDIE;
+ }
+ constructTypeDIE(TyDIE, CTy);
+ } else {
+ constructTypeDIE(TyDIE, cast<DIDerivedType>(Ty));
+ }
+
+ return &TyDIE;
+}
+
DIE *DwarfUnit::getOrCreateTypeDIE(const MDNode *TyNode) {
if (!TyNode)
return nullptr;
@@ -627,43 +670,23 @@ DIE *DwarfUnit::getOrCreateTypeDIE(const MDNode *TyNode) {
// DW_TAG_restrict_type is not supported in DWARF2
if (Ty->getTag() == dwarf::DW_TAG_restrict_type && DD->getDwarfVersion() <= 2)
- return getOrCreateTypeDIE(resolve(cast<DIDerivedType>(Ty)->getBaseType()));
+ return getOrCreateTypeDIE(cast<DIDerivedType>(Ty)->getBaseType());
// DW_TAG_atomic_type is not supported in DWARF < 5
if (Ty->getTag() == dwarf::DW_TAG_atomic_type && DD->getDwarfVersion() < 5)
- return getOrCreateTypeDIE(resolve(cast<DIDerivedType>(Ty)->getBaseType()));
+ return getOrCreateTypeDIE(cast<DIDerivedType>(Ty)->getBaseType());
// Construct the context before querying for the existence of the DIE in case
// such construction creates the DIE.
- auto *Context = resolve(Ty->getScope());
+ auto *Context = Ty->getScope();
DIE *ContextDIE = getOrCreateContextDIE(Context);
assert(ContextDIE);
if (DIE *TyDIE = getDIE(Ty))
return TyDIE;
- // Create new type.
- DIE &TyDIE = createAndAddDIE(Ty->getTag(), *ContextDIE, Ty);
-
- updateAcceleratorTables(Context, Ty, TyDIE);
-
- if (auto *BT = dyn_cast<DIBasicType>(Ty))
- constructTypeDIE(TyDIE, BT);
- else if (auto *STy = dyn_cast<DISubroutineType>(Ty))
- constructTypeDIE(TyDIE, STy);
- else if (auto *CTy = dyn_cast<DICompositeType>(Ty)) {
- 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.
- return &TyDIE;
- }
- constructTypeDIE(TyDIE, CTy);
- } else {
- constructTypeDIE(TyDIE, cast<DIDerivedType>(Ty));
- }
-
- return &TyDIE;
+ return static_cast<DwarfUnit *>(ContextDIE->getUnit())
+ ->createTypeDIE(Context, *ContextDIE, Ty);
}
void DwarfUnit::updateAcceleratorTables(const DIScope *Context,
@@ -679,7 +702,7 @@ void DwarfUnit::updateAcceleratorTables(const DIScope *Context,
DD->addAccelType(*CUNode, Ty->getName(), TyDIE, Flags);
if (!Context || isa<DICompileUnit>(Context) || isa<DIFile>(Context) ||
- isa<DINamespace>(Context))
+ isa<DINamespace>(Context) || isa<DICommonBlock>(Context))
addGlobalType(Ty, TyDIE, Context);
}
}
@@ -702,8 +725,8 @@ std::string DwarfUnit::getParentContextString(const DIScope *Context) const {
SmallVector<const DIScope *, 1> Parents;
while (!isa<DICompileUnit>(Context)) {
Parents.push_back(Context);
- if (Context->getScope())
- Context = resolve(Context->getScope());
+ if (const DIScope *S = Context->getScope())
+ Context = S;
else
// Structure, etc types will have a NULL context if they're at the top
// level.
@@ -754,7 +777,7 @@ void DwarfUnit::constructTypeDIE(DIE &Buffer, const DIDerivedType *DTy) {
uint16_t Tag = Buffer.getTag();
// Map to main type, void will not have a type.
- const DIType *FromTy = resolve(DTy->getBaseType());
+ const DIType *FromTy = DTy->getBaseType();
if (FromTy)
addType(Buffer, FromTy);
@@ -770,24 +793,23 @@ void DwarfUnit::constructTypeDIE(DIE &Buffer, const DIDerivedType *DTy) {
addUInt(Buffer, dwarf::DW_AT_byte_size, None, Size);
if (Tag == dwarf::DW_TAG_ptr_to_member_type)
- addDIEEntry(
- Buffer, dwarf::DW_AT_containing_type,
- *getOrCreateTypeDIE(resolve(cast<DIDerivedType>(DTy)->getClassType())));
+ addDIEEntry(Buffer, dwarf::DW_AT_containing_type,
+ *getOrCreateTypeDIE(cast<DIDerivedType>(DTy)->getClassType()));
// Add source line info if available and TyDesc is not a forward declaration.
if (!DTy->isForwardDecl())
addSourceLine(Buffer, DTy);
- // If DWARF address space value is other than None, add it for pointer and
- // reference types as DW_AT_address_class.
- if (DTy->getDWARFAddressSpace() && (Tag == dwarf::DW_TAG_pointer_type ||
- Tag == dwarf::DW_TAG_reference_type))
+ // If DWARF address space value is other than None, add it. The IR
+ // verifier checks that DWARF address space only exists for pointer
+ // or reference types.
+ if (DTy->getDWARFAddressSpace())
addUInt(Buffer, dwarf::DW_AT_address_class, dwarf::DW_FORM_data4,
DTy->getDWARFAddressSpace().getValue());
}
void DwarfUnit::constructSubprogramArguments(DIE &Buffer, DITypeRefArray Args) {
for (unsigned i = 1, N = Args.size(); i < N; ++i) {
- const DIType *Ty = resolve(Args[i]);
+ const DIType *Ty = Args[i];
if (!Ty) {
assert(i == N-1 && "Unspecified parameter must be the last argument");
createAndAddDIE(dwarf::DW_TAG_unspecified_parameters, Buffer);
@@ -804,7 +826,7 @@ void DwarfUnit::constructTypeDIE(DIE &Buffer, const DISubroutineType *CTy) {
// Add return type. A void return won't have a type.
auto Elements = cast<DISubroutineType>(CTy)->getTypeArray();
if (Elements.size())
- if (auto RTy = resolve(Elements[0]))
+ if (auto RTy = Elements[0])
addType(Buffer, RTy);
bool isPrototyped = true;
@@ -875,7 +897,7 @@ void DwarfUnit::constructTypeDIE(DIE &Buffer, const DICompositeType *CTy) {
else if (auto *DDTy = dyn_cast<DIDerivedType>(Element)) {
if (DDTy->getTag() == dwarf::DW_TAG_friend) {
DIE &ElemDie = createAndAddDIE(dwarf::DW_TAG_friend, Buffer);
- addType(ElemDie, resolve(DDTy->getBaseType()), dwarf::DW_AT_friend);
+ addType(ElemDie, DDTy->getBaseType(), dwarf::DW_AT_friend);
} else if (DDTy->isStaticMember()) {
getOrCreateStaticMemberDIE(DDTy);
} else if (Tag == dwarf::DW_TAG_variant_part) {
@@ -884,7 +906,7 @@ void DwarfUnit::constructTypeDIE(DIE &Buffer, const DICompositeType *CTy) {
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())))
+ if (isUnsignedDIType(DD, Discriminator->getBaseType()))
addUInt(Variant, dwarf::DW_AT_discr_value, None, CI->getZExtValue());
else
addSInt(Variant, dwarf::DW_AT_discr_value, None, CI->getSExtValue());
@@ -898,7 +920,7 @@ void DwarfUnit::constructTypeDIE(DIE &Buffer, const DICompositeType *CTy) {
StringRef PropertyName = Property->getName();
addString(ElemDie, dwarf::DW_AT_APPLE_property_name, PropertyName);
if (Property->getType())
- addType(ElemDie, resolve(Property->getType()));
+ addType(ElemDie, Property->getType());
addSourceLine(ElemDie, Property);
StringRef GetterName = Property->getGetterName();
if (!GetterName.empty())
@@ -924,7 +946,7 @@ void DwarfUnit::constructTypeDIE(DIE &Buffer, const DICompositeType *CTy) {
// inside C++ composite types to point to the base class with the vtable.
// Rust uses DW_AT_containing_type to link a vtable to the type
// for which it was created.
- if (auto *ContainingType = resolve(CTy->getVTableHolder()))
+ if (auto *ContainingType = CTy->getVTableHolder())
addDIEEntry(Buffer, dwarf::DW_AT_containing_type,
*getOrCreateTypeDIE(ContainingType));
@@ -994,7 +1016,7 @@ void DwarfUnit::constructTemplateTypeParameterDIE(
createAndAddDIE(dwarf::DW_TAG_template_type_parameter, Buffer);
// Add the type if it exists, it could be void and therefore no type.
if (TP->getType())
- addType(ParamDIE, resolve(TP->getType()));
+ addType(ParamDIE, TP->getType());
if (!TP->getName().empty())
addString(ParamDIE, dwarf::DW_AT_name, TP->getName());
}
@@ -1006,12 +1028,12 @@ void DwarfUnit::constructTemplateValueParameterDIE(
// Add the type if there is one, template template and template parameter
// packs will not have a type.
if (VP->getTag() == dwarf::DW_TAG_template_value_parameter)
- addType(ParamDIE, resolve(VP->getType()));
+ addType(ParamDIE, VP->getType());
if (!VP->getName().empty())
addString(ParamDIE, dwarf::DW_AT_name, VP->getName());
if (Metadata *Val = VP->getValue()) {
if (ConstantInt *CI = mdconst::dyn_extract<ConstantInt>(Val))
- addConstantValue(ParamDIE, CI, resolve(VP->getType()));
+ addConstantValue(ParamDIE, CI, VP->getType());
else if (GlobalValue *GV = mdconst::dyn_extract<GlobalValue>(Val)) {
// We cannot describe the location of dllimport'd entities: the
// computation of their address requires loads from the IAT.
@@ -1085,7 +1107,7 @@ DIE *DwarfUnit::getOrCreateSubprogramDIE(const DISubprogram *SP, bool Minimal) {
// such construction creates the DIE (as is the case for member function
// declarations).
DIE *ContextDIE =
- Minimal ? &getUnitDie() : getOrCreateContextDIE(resolve(SP->getScope()));
+ Minimal ? &getUnitDie() : getOrCreateContextDIE(SP->getScope());
if (DIE *SPDie = getDIE(SP))
return SPDie;
@@ -1107,7 +1129,8 @@ DIE *DwarfUnit::getOrCreateSubprogramDIE(const DISubprogram *SP, bool Minimal) {
if (SP->isDefinition())
return &SPDie;
- applySubprogramAttributes(SP, SPDie);
+ static_cast<DwarfUnit *>(SPDie.getUnit())
+ ->applySubprogramAttributes(SP, SPDie);
return &SPDie;
}
@@ -1197,7 +1220,7 @@ void DwarfUnit::applySubprogramAttributes(const DISubprogram *SP, DIE &SPDie,
// Add a return type. If this is a type like a C/C++ void type we don't add a
// return type.
if (Args.size())
- if (auto Ty = resolve(Args[0]))
+ if (auto Ty = Args[0])
addType(SPDie, Ty);
unsigned VK = SP->getVirtuality();
@@ -1209,8 +1232,7 @@ void DwarfUnit::applySubprogramAttributes(const DISubprogram *SP, DIE &SPDie,
addUInt(*Block, dwarf::DW_FORM_udata, SP->getVirtualIndex());
addBlock(SPDie, dwarf::DW_AT_vtable_elem_location, Block);
}
- ContainingTypeMap.insert(
- std::make_pair(&SPDie, resolve(SP->getContainingType())));
+ ContainingTypeMap.insert(std::make_pair(&SPDie, SP->getContainingType()));
}
if (!SP->isDefinition()) {
@@ -1261,6 +1283,12 @@ void DwarfUnit::applySubprogramAttributes(const DISubprogram *SP, DIE &SPDie,
if (SP->isMainSubprogram())
addFlag(SPDie, dwarf::DW_AT_main_subprogram);
+ if (SP->isPure())
+ addFlag(SPDie, dwarf::DW_AT_pure);
+ if (SP->isElemental())
+ addFlag(SPDie, dwarf::DW_AT_elemental);
+ if (SP->isRecursive())
+ addFlag(SPDie, dwarf::DW_AT_recursive);
}
void DwarfUnit::constructSubrangeDIE(DIE &Buffer, const DISubrange *SR,
@@ -1310,7 +1338,7 @@ static bool hasVectorBeenPadded(const DICompositeType *CTy) {
const uint64_t ActualSize = CTy->getSizeInBits();
// Obtain the size of each element in the vector.
- DIType *BaseTy = CTy->getBaseType().resolve();
+ DIType *BaseTy = CTy->getBaseType();
assert(BaseTy && "Unknown vector element type.");
const uint64_t ElementSize = BaseTy->getSizeInBits();
@@ -1338,7 +1366,7 @@ void DwarfUnit::constructArrayTypeDIE(DIE &Buffer, const DICompositeType *CTy) {
}
// Emit the element type.
- addType(Buffer, resolve(CTy->getBaseType()));
+ addType(Buffer, CTy->getBaseType());
// Get an anonymous type for index type.
// FIXME: This type should be passed down from the front end
@@ -1356,7 +1384,7 @@ void DwarfUnit::constructArrayTypeDIE(DIE &Buffer, const DICompositeType *CTy) {
}
void DwarfUnit::constructEnumTypeDIE(DIE &Buffer, const DICompositeType *CTy) {
- const DIType *DTy = resolve(CTy->getBaseType());
+ const DIType *DTy = CTy->getBaseType();
bool IsUnsigned = DTy && isUnsignedDIType(DD, DTy);
if (DTy) {
if (DD->getDwarfVersion() >= 3)
@@ -1365,6 +1393,9 @@ void DwarfUnit::constructEnumTypeDIE(DIE &Buffer, const DICompositeType *CTy) {
addFlag(Buffer, dwarf::DW_AT_enum_class);
}
+ auto *Context = CTy->getScope();
+ bool IndexEnumerators = !Context || isa<DICompileUnit>(Context) || isa<DIFile>(Context) ||
+ isa<DINamespace>(Context) || isa<DICommonBlock>(Context);
DINodeArray Elements = CTy->getElements();
// Add enumerators to enumeration type.
@@ -1376,6 +1407,8 @@ void DwarfUnit::constructEnumTypeDIE(DIE &Buffer, const DICompositeType *CTy) {
addString(Enumerator, dwarf::DW_AT_name, Name);
auto Value = static_cast<uint64_t>(Enum->getValue());
addConstantValue(Enumerator, IsUnsigned, Value);
+ if (IndexEnumerators)
+ addGlobalName(Name, Enumerator, Context);
}
}
}
@@ -1400,7 +1433,7 @@ DIE &DwarfUnit::constructMemberDIE(DIE &Buffer, const DIDerivedType *DT) {
if (!Name.empty())
addString(MemberDie, dwarf::DW_AT_name, Name);
- if (DIType *Resolved = resolve(DT->getBaseType()))
+ if (DIType *Resolved = DT->getBaseType())
addType(MemberDie, Resolved);
addSourceLine(MemberDie, DT);
@@ -1509,7 +1542,7 @@ DIE *DwarfUnit::getOrCreateStaticMemberDIE(const DIDerivedType *DT) {
// Construct the context before querying for the existence of the DIE in case
// such construction creates the DIE.
- DIE *ContextDIE = getOrCreateContextDIE(resolve(DT->getScope()));
+ DIE *ContextDIE = getOrCreateContextDIE(DT->getScope());
assert(dwarf::isType(ContextDIE->getTag()) &&
"Static member should belong to a type.");
@@ -1518,7 +1551,7 @@ DIE *DwarfUnit::getOrCreateStaticMemberDIE(const DIDerivedType *DT) {
DIE &StaticMemberDIE = createAndAddDIE(DT->getTag(), *ContextDIE, DT);
- const DIType *Ty = resolve(DT->getBaseType());
+ const DIType *Ty = DT->getBaseType();
addString(StaticMemberDIE, dwarf::DW_AT_name, DT->getName());
addType(StaticMemberDIE, Ty);
@@ -1671,3 +1704,11 @@ void DwarfUnit::addLoclistsBase() {
DU->getLoclistsTableBaseSym(),
TLOF.getDwarfLoclistsSection()->getBeginSymbol());
}
+
+void DwarfTypeUnit::finishNonUnitTypeDIE(DIE& D, const DICompositeType *CTy) {
+ addFlag(D, dwarf::DW_AT_declaration);
+ StringRef Name = CTy->getName();
+ if (!Name.empty())
+ addString(D, dwarf::DW_AT_name, Name);
+ getCU().createTypeDIE(CTy);
+}
diff --git a/lib/CodeGen/AsmPrinter/DwarfUnit.h b/lib/CodeGen/AsmPrinter/DwarfUnit.h
index a59ebb7c1465..56c934a35ae8 100644
--- a/lib/CodeGen/AsmPrinter/DwarfUnit.h
+++ b/lib/CodeGen/AsmPrinter/DwarfUnit.h
@@ -1,9 +1,8 @@
//===-- llvm/CodeGen/DwarfUnit.h - Dwarf Compile Unit ---*- C++ -*--===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -199,6 +198,7 @@ public:
void addConstantValue(DIE &Die, const ConstantInt *CI, const DIType *Ty);
void addConstantValue(DIE &Die, const APInt &Val, const DIType *Ty);
void addConstantValue(DIE &Die, const APInt &Val, bool Unsigned);
+ void addConstantValue(DIE &Die, uint64_t Val, const DIType *Ty);
void addConstantValue(DIE &Die, bool Unsigned, uint64_t Val);
/// Add constant value entry in variable DIE.
@@ -237,6 +237,9 @@ public:
void applySubprogramAttributes(const DISubprogram *SP, DIE &SPDie,
bool SkipSPAttributes = false);
+ /// Creates type DIE with specific context.
+ DIE *createTypeDIE(const DIScope *Context, DIE &ContextDIE, const DIType *Ty);
+
/// Find existing DIE or create new DIE for the given type.
DIE *getOrCreateTypeDIE(const MDNode *TyNode);
@@ -294,7 +297,10 @@ public:
/// If the \p File has an MD5 checksum, return it as an MD5Result
/// allocated in the MCContext.
- MD5::MD5Result *getMD5AsBytes(const DIFile *File) const;
+ Optional<MD5::MD5Result> getMD5AsBytes(const DIFile *File) const;
+
+ /// Get context owner's DIE.
+ DIE *createTypeDIE(const DICompositeType *Ty);
protected:
~DwarfUnit();
@@ -306,17 +312,6 @@ protected:
/// 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.
- template <typename T> T *resolve(TypedDINodeRef<T> Ref) const {
- return Ref.resolve();
- }
-
- /// If this is a named finished type then include it in the list of types for
- /// the accelerator tables.
- void updateAcceleratorTables(const DIScope *Context, const DIType *Ty,
- const DIE &TyDIE);
-
/// Emit the common part of the header for this unit.
void emitCommonHeader(bool UseOffsets, dwarf::UnitType UT);
@@ -344,6 +339,13 @@ private:
/// Set D as anonymous type for index which can be reused later.
void setIndexTyDie(DIE *D) { IndexTyDie = D; }
+ virtual void finishNonUnitTypeDIE(DIE& D, const DICompositeType *CTy) = 0;
+
+ /// If this is a named finished type then include it in the list of types for
+ /// the accelerator tables.
+ void updateAcceleratorTables(const DIScope *Context, const DIType *Ty,
+ const DIE &TyDIE);
+
virtual bool isDwoUnit() const = 0;
const MCSymbol *getCrossSectionRelativeBaseAddress() const override;
};
@@ -356,6 +358,7 @@ class DwarfTypeUnit final : public DwarfUnit {
bool UsedLineTable = false;
unsigned getOrCreateSourceID(const DIFile *File) override;
+ void finishNonUnitTypeDIE(DIE& D, const DICompositeType *CTy) override;
bool isDwoUnit() const override;
public:
@@ -365,9 +368,6 @@ public:
void setTypeSignature(uint64_t Signature) { TypeSignature = Signature; }
void setType(const DIE *Ty) { this->Ty = Ty; }
- /// Get context owner's DIE.
- DIE *createTypeDIE(const DICompositeType *Ty);
-
/// Emit the header for this unit, not including the initial length field.
void emitHeader(bool UseOffsets) override;
unsigned getHeaderSize() const override {
diff --git a/lib/CodeGen/AsmPrinter/EHStreamer.cpp b/lib/CodeGen/AsmPrinter/EHStreamer.cpp
index 7599121de2b0..99e3687b36b8 100644
--- a/lib/CodeGen/AsmPrinter/EHStreamer.cpp
+++ b/lib/CodeGen/AsmPrinter/EHStreamer.cpp
@@ -1,9 +1,8 @@
//===- CodeGen/AsmPrinter/EHStreamer.cpp - Exception Directive Streamer ---===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -379,7 +378,8 @@ MCSymbol *EHStreamer::emitExceptionTable() {
bool IsSJLJ = Asm->MAI->getExceptionHandlingType() == ExceptionHandling::SjLj;
bool IsWasm = Asm->MAI->getExceptionHandlingType() == ExceptionHandling::Wasm;
unsigned CallSiteEncoding =
- IsSJLJ ? dwarf::DW_EH_PE_udata4 : dwarf::DW_EH_PE_uleb128;
+ IsSJLJ ? static_cast<unsigned>(dwarf::DW_EH_PE_udata4) :
+ Asm->getObjFileLowering().getCallSiteEncoding();
bool HaveTTData = !TypeInfos.empty() || !FilterIds.empty();
// Type infos.
@@ -524,24 +524,24 @@ MCSymbol *EHStreamer::emitExceptionTable() {
// Offset of the call site relative to the start of the procedure.
if (VerboseAsm)
Asm->OutStreamer->AddComment(">> Call Site " + Twine(++Entry) + " <<");
- Asm->EmitLabelDifferenceAsULEB128(BeginLabel, EHFuncBeginSym);
+ Asm->EmitCallSiteOffset(BeginLabel, EHFuncBeginSym, CallSiteEncoding);
if (VerboseAsm)
Asm->OutStreamer->AddComment(Twine(" Call between ") +
BeginLabel->getName() + " and " +
EndLabel->getName());
- Asm->EmitLabelDifferenceAsULEB128(EndLabel, BeginLabel);
+ Asm->EmitCallSiteOffset(EndLabel, BeginLabel, CallSiteEncoding);
// 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->EmitULEB128(0);
+ Asm->EmitCallSiteValue(0, CallSiteEncoding);
} else {
if (VerboseAsm)
Asm->OutStreamer->AddComment(Twine(" jumps to ") +
S.LPad->LandingPadLabel->getName());
- Asm->EmitLabelDifferenceAsULEB128(S.LPad->LandingPadLabel,
- EHFuncBeginSym);
+ Asm->EmitCallSiteOffset(S.LPad->LandingPadLabel, EHFuncBeginSym,
+ CallSiteEncoding);
}
// Offset of the first associated action record, relative to the start of
diff --git a/lib/CodeGen/AsmPrinter/EHStreamer.h b/lib/CodeGen/AsmPrinter/EHStreamer.h
index ce912d032c6d..e62cf17a05d4 100644
--- a/lib/CodeGen/AsmPrinter/EHStreamer.h
+++ b/lib/CodeGen/AsmPrinter/EHStreamer.h
@@ -1,9 +1,8 @@
//===- EHStreamer.h - Exception Handling Directive Streamer -----*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
diff --git a/lib/CodeGen/AsmPrinter/ErlangGCPrinter.cpp b/lib/CodeGen/AsmPrinter/ErlangGCPrinter.cpp
index 34677ecc9e69..39392b79e960 100644
--- a/lib/CodeGen/AsmPrinter/ErlangGCPrinter.cpp
+++ b/lib/CodeGen/AsmPrinter/ErlangGCPrinter.cpp
@@ -1,9 +1,8 @@
//===- ErlangGCPrinter.cpp - Erlang/OTP frametable emitter ----------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
diff --git a/lib/CodeGen/AsmPrinter/OcamlGCPrinter.cpp b/lib/CodeGen/AsmPrinter/OcamlGCPrinter.cpp
index 3479a00def23..3145cc90dc73 100644
--- a/lib/CodeGen/AsmPrinter/OcamlGCPrinter.cpp
+++ b/lib/CodeGen/AsmPrinter/OcamlGCPrinter.cpp
@@ -1,9 +1,8 @@
//===- OcamlGCPrinter.cpp - Ocaml frametable emitter ----------------------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
diff --git a/lib/CodeGen/AsmPrinter/WasmException.cpp b/lib/CodeGen/AsmPrinter/WasmException.cpp
index 527e5ae50146..444b0ed17b6d 100644
--- a/lib/CodeGen/AsmPrinter/WasmException.cpp
+++ b/lib/CodeGen/AsmPrinter/WasmException.cpp
@@ -1,9 +1,8 @@
//===-- CodeGen/AsmPrinter/WasmException.cpp - Wasm Exception Impl --------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -19,10 +18,10 @@
using namespace llvm;
void WasmException::endModule() {
- // This is the symbol used in 'throw' and 'if_except' instruction to denote
+ // This is the symbol used in 'throw' and 'br_on_exn' instruction to denote
// this is a C++ exception. This symbol has to be emitted somewhere once in
// the module. Check if the symbol has already been created, i.e., we have at
- // least one 'throw' or 'if_except' instruction in the module, and emit the
+ // least one 'throw' or 'br_on_exn' instruction in the module, and emit the
// symbol only if so.
SmallString<60> NameStr;
Mangler::getNameWithPrefix(NameStr, "__cpp_exception", Asm->getDataLayout());
diff --git a/lib/CodeGen/AsmPrinter/WasmException.h b/lib/CodeGen/AsmPrinter/WasmException.h
index cbdb42457cf8..1893b6b2df43 100644
--- a/lib/CodeGen/AsmPrinter/WasmException.h
+++ b/lib/CodeGen/AsmPrinter/WasmException.h
@@ -1,9 +1,8 @@
//===-- WasmException.h - Wasm Exception Framework -------------*- C++ -*--===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
diff --git a/lib/CodeGen/AsmPrinter/WinCFGuard.cpp b/lib/CodeGen/AsmPrinter/WinCFGuard.cpp
index 18d37caf57ee..290be81c6baa 100644
--- a/lib/CodeGen/AsmPrinter/WinCFGuard.cpp
+++ b/lib/CodeGen/AsmPrinter/WinCFGuard.cpp
@@ -1,9 +1,8 @@
//===-- 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.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
diff --git a/lib/CodeGen/AsmPrinter/WinCFGuard.h b/lib/CodeGen/AsmPrinter/WinCFGuard.h
index 28f119e35966..def0a59ab007 100644
--- a/lib/CodeGen/AsmPrinter/WinCFGuard.h
+++ b/lib/CodeGen/AsmPrinter/WinCFGuard.h
@@ -1,9 +1,8 @@
//===-- 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.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
diff --git a/lib/CodeGen/AsmPrinter/WinException.cpp b/lib/CodeGen/AsmPrinter/WinException.cpp
index cf8e8c69bc2a..155e91ce61a1 100644
--- a/lib/CodeGen/AsmPrinter/WinException.cpp
+++ b/lib/CodeGen/AsmPrinter/WinException.cpp
@@ -1,9 +1,8 @@
//===-- CodeGen/AsmPrinter/WinException.cpp - Dwarf Exception Impl ------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -110,6 +109,12 @@ void WinException::beginFunction(const MachineFunction *MF) {
beginFunclet(MF->front(), Asm->CurrentFnSym);
}
+void WinException::markFunctionEnd() {
+ if (isAArch64 && CurrentFuncletEntry &&
+ (shouldEmitMoves || shouldEmitPersonality))
+ Asm->OutStreamer->EmitWinCFIFuncletOrFuncEnd();
+}
+
/// endFunction - Gather and emit post-function exception information.
///
void WinException::endFunction(const MachineFunction *MF) {
@@ -129,7 +134,7 @@ void WinException::endFunction(const MachineFunction *MF) {
NonConstMF->tidyLandingPads();
}
- endFunclet();
+ endFuncletImpl();
// endFunclet will emit the necessary .xdata tables for x64 SEH.
if (Per == EHPersonality::MSVC_Win64SEH && MF->hasEHFunclets())
@@ -232,6 +237,15 @@ void WinException::beginFunclet(const MachineBasicBlock &MBB,
}
void WinException::endFunclet() {
+ if (isAArch64 && CurrentFuncletEntry &&
+ (shouldEmitMoves || shouldEmitPersonality)) {
+ Asm->OutStreamer->SwitchSection(CurrentFuncletTextSection);
+ Asm->OutStreamer->EmitWinCFIFuncletOrFuncEnd();
+ }
+ endFuncletImpl();
+}
+
+void WinException::endFuncletImpl() {
// No funclet to process? Great, we have nothing to do.
if (!CurrentFuncletEntry)
return;
@@ -247,8 +261,6 @@ void WinException::endFunclet() {
// to EmitWinEHHandlerData below can calculate the size of the funclet or
// function.
if (isAArch64) {
- Asm->OutStreamer->SwitchSection(CurrentFuncletTextSection);
- Asm->OutStreamer->EmitWinCFIFuncletOrFuncEnd();
MCSection *XData = Asm->OutStreamer->getAssociatedXDataSection(
Asm->OutStreamer->getCurrentSectionOnly());
Asm->OutStreamer->SwitchSection(XData);
@@ -545,15 +557,17 @@ void WinException::emitCSpecificHandlerTable(const MachineFunction *MF) {
OS.AddComment(Comment);
};
- // Emit a label assignment with the SEH frame offset so we can use it for
- // llvm.eh.recoverfp.
- StringRef FLinkageName =
- GlobalValue::dropLLVMManglingEscape(MF->getFunction().getName());
- MCSymbol *ParentFrameOffset =
- Ctx.getOrCreateParentFrameOffsetSymbol(FLinkageName);
- const MCExpr *MCOffset =
- MCConstantExpr::create(FuncInfo.SEHSetFrameOffset, Ctx);
- Asm->OutStreamer->EmitAssignment(ParentFrameOffset, MCOffset);
+ if (!isAArch64) {
+ // Emit a label assignment with the SEH frame offset so we can use it for
+ // llvm.eh.recoverfp.
+ StringRef FLinkageName =
+ GlobalValue::dropLLVMManglingEscape(MF->getFunction().getName());
+ MCSymbol *ParentFrameOffset =
+ Ctx.getOrCreateParentFrameOffsetSymbol(FLinkageName);
+ const MCExpr *MCOffset =
+ MCConstantExpr::create(FuncInfo.SEHSetFrameOffset, Ctx);
+ Asm->OutStreamer->EmitAssignment(ParentFrameOffset, MCOffset);
+ }
// Use the assembler to compute the number of table entries through label
// difference and division.
@@ -936,8 +950,7 @@ void WinException::emitEHRegistrationOffsetLabel(const WinEHFuncInfo &FuncInfo,
int FI = FuncInfo.EHRegNodeFrameIndex;
if (FI != INT_MAX) {
const TargetFrameLowering *TFI = Asm->MF->getSubtarget().getFrameLowering();
- unsigned UnusedReg;
- Offset = TFI->getFrameIndexReference(*Asm->MF, FI, UnusedReg);
+ Offset = TFI->getNonLocalFrameIndexReference(*Asm->MF, FI);
}
MCContext &Ctx = Asm->OutContext;
diff --git a/lib/CodeGen/AsmPrinter/WinException.h b/lib/CodeGen/AsmPrinter/WinException.h
index 37c796f89765..dc5036302131 100644
--- a/lib/CodeGen/AsmPrinter/WinException.h
+++ b/lib/CodeGen/AsmPrinter/WinException.h
@@ -1,9 +1,8 @@
//===-- WinException.h - Windows Exception Handling ----------*- C++ -*--===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -86,6 +85,7 @@ class LLVM_LIBRARY_VISIBILITY WinException : public EHStreamer {
/// only), it is relative to the frame pointer.
int getFrameIndexOffset(int FrameIndex, const WinEHFuncInfo &FuncInfo);
+ void endFuncletImpl();
public:
//===--------------------------------------------------------------------===//
// Main entry points.
@@ -100,6 +100,8 @@ public:
/// immediately after the function entry point.
void beginFunction(const MachineFunction *MF) override;
+ void markFunctionEnd() override;
+
/// Gather and emit post-function exception information.
void endFunction(const MachineFunction *) override;