summaryrefslogtreecommitdiff
path: root/contrib/llvm/lib/CodeGen/AsmPrinter
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/lib/CodeGen/AsmPrinter')
-rw-r--r--contrib/llvm/lib/CodeGen/AsmPrinter/AccelTable.cpp17
-rw-r--r--contrib/llvm/lib/CodeGen/AsmPrinter/AddressPool.cpp18
-rw-r--r--contrib/llvm/lib/CodeGen/AsmPrinter/AddressPool.h6
-rw-r--r--contrib/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp128
-rw-r--r--contrib/llvm/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp3
-rw-r--r--contrib/llvm/lib/CodeGen/AsmPrinter/AsmPrinterHandler.h74
-rw-r--r--contrib/llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp115
-rw-r--r--contrib/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp850
-rw-r--r--contrib/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h104
-rw-r--r--contrib/llvm/lib/CodeGen/AsmPrinter/DIE.cpp9
-rw-r--r--contrib/llvm/lib/CodeGen/AsmPrinter/DbgEntityHistoryCalculator.cpp (renamed from contrib/llvm/lib/CodeGen/AsmPrinter/DbgValueHistoryCalculator.cpp)90
-rw-r--r--contrib/llvm/lib/CodeGen/AsmPrinter/DbgValueHistoryCalculator.h67
-rw-r--r--contrib/llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp29
-rw-r--r--contrib/llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.h131
-rw-r--r--contrib/llvm/lib/CodeGen/AsmPrinter/DebugLocEntry.h2
-rw-r--r--contrib/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp202
-rw-r--r--contrib/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h50
-rw-r--r--contrib/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp806
-rw-r--r--contrib/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h180
-rw-r--r--contrib/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp33
-rw-r--r--contrib/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h5
-rw-r--r--contrib/llvm/lib/CodeGen/AsmPrinter/DwarfFile.cpp30
-rw-r--r--contrib/llvm/lib/CodeGen/AsmPrinter/DwarfFile.h69
-rw-r--r--contrib/llvm/lib/CodeGen/AsmPrinter/DwarfStringPool.cpp49
-rw-r--r--contrib/llvm/lib/CodeGen/AsmPrinter/DwarfStringPool.h10
-rw-r--r--contrib/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp194
-rw-r--r--contrib/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h35
-rw-r--r--contrib/llvm/lib/CodeGen/AsmPrinter/EHStreamer.cpp39
-rw-r--r--contrib/llvm/lib/CodeGen/AsmPrinter/EHStreamer.h13
-rw-r--r--contrib/llvm/lib/CodeGen/AsmPrinter/ErlangGCPrinter.cpp2
-rw-r--r--contrib/llvm/lib/CodeGen/AsmPrinter/OcamlGCPrinter.cpp2
-rw-r--r--contrib/llvm/lib/CodeGen/AsmPrinter/WasmException.cpp97
-rw-r--r--contrib/llvm/lib/CodeGen/AsmPrinter/WasmException.h42
-rw-r--r--contrib/llvm/lib/CodeGen/AsmPrinter/WinCFGuard.h2
-rw-r--r--contrib/llvm/lib/CodeGen/AsmPrinter/WinException.cpp28
-rw-r--r--contrib/llvm/lib/CodeGen/AsmPrinter/WinException.h7
36 files changed, 2223 insertions, 1315 deletions
diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/AccelTable.cpp b/contrib/llvm/lib/CodeGen/AsmPrinter/AccelTable.cpp
index 20b0b8d3feab..95875ccb8a0b 100644
--- a/contrib/llvm/lib/CodeGen/AsmPrinter/AccelTable.cpp
+++ b/contrib/llvm/lib/CodeGen/AsmPrinter/AccelTable.cpp
@@ -23,6 +23,7 @@
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/Support/raw_ostream.h"
+#include "llvm/Target/TargetLoweringObjectFile.h"
#include <algorithm>
#include <cstddef>
#include <cstdint>
@@ -553,19 +554,31 @@ void llvm::emitDWARF5AccelTable(
AsmPrinter *Asm, AccelTable<DWARF5AccelTableData> &Contents,
const DwarfDebug &DD, ArrayRef<std::unique_ptr<DwarfCompileUnit>> CUs) {
std::vector<MCSymbol *> CompUnits;
+ SmallVector<unsigned, 1> CUIndex(CUs.size());
+ int Count = 0;
for (const auto &CU : enumerate(CUs)) {
+ if (CU.value()->getCUNode()->getNameTableKind() ==
+ DICompileUnit::DebugNameTableKind::None)
+ continue;
+ CUIndex[CU.index()] = Count++;
assert(CU.index() == CU.value()->getUniqueID());
const DwarfCompileUnit *MainCU =
DD.useSplitDwarf() ? CU.value()->getSkeleton() : CU.value().get();
CompUnits.push_back(MainCU->getLabelBegin());
}
+ if (CompUnits.empty())
+ return;
+
+ Asm->OutStreamer->SwitchSection(
+ Asm->getObjFileLowering().getDwarfDebugNamesSection());
+
Contents.finalize(Asm, "names");
Dwarf5AccelTableWriter<DWARF5AccelTableData>(
Asm, Contents, CompUnits,
- [&DD](const DWARF5AccelTableData &Entry) {
+ [&](const DWARF5AccelTableData &Entry) {
const DIE *CUDie = Entry.getDie().getUnitDie();
- return DD.lookupCU(CUDie)->getUniqueID();
+ return CUIndex[DD.lookupCU(CUDie)->getUniqueID()];
})
.emit();
}
diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/AddressPool.cpp b/contrib/llvm/lib/CodeGen/AsmPrinter/AddressPool.cpp
index c8305ad9c547..042243b79259 100644
--- a/contrib/llvm/lib/CodeGen/AsmPrinter/AddressPool.cpp
+++ b/contrib/llvm/lib/CodeGen/AsmPrinter/AddressPool.cpp
@@ -27,29 +27,35 @@ unsigned AddressPool::getIndex(const MCSymbol *Sym, bool TLS) {
void AddressPool::emitHeader(AsmPrinter &Asm, MCSection *Section) {
static const uint8_t AddrSize = Asm.getDataLayout().getPointerSize();
- Asm.OutStreamer->SwitchSection(Section);
-
uint64_t Length = sizeof(uint16_t) // version
+ sizeof(uint8_t) // address_size
+ sizeof(uint8_t) // segment_selector_size
+ AddrSize * Pool.size(); // entries
+ Asm.OutStreamer->AddComment("Length of contribution");
Asm.emitInt32(Length); // TODO: Support DWARF64 format.
+ 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.
}
// Emit addresses into the section given.
void AddressPool::emit(AsmPrinter &Asm, MCSection *AddrSection) {
- if (Asm.getDwarfVersion() >= 5)
- emitHeader(Asm, AddrSection);
-
- if (Pool.empty())
+ if (isEmpty())
return;
// Start the dwarf addr section.
Asm.OutStreamer->SwitchSection(AddrSection);
+ if (Asm.getDwarfVersion() >= 5)
+ emitHeader(Asm, AddrSection);
+
+ // Define the symbol that marks the start of the contribution.
+ // It is referenced via DW_AT_addr_base.
+ Asm.OutStreamer->EmitLabel(AddressTableBaseSym);
+
// Order the address pool entries by ID
SmallVector<const MCExpr *, 64> Entries(Pool.size());
diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/AddressPool.h b/contrib/llvm/lib/CodeGen/AsmPrinter/AddressPool.h
index d5008fab5563..2209c7eb50ed 100644
--- a/contrib/llvm/lib/CodeGen/AsmPrinter/AddressPool.h
+++ b/contrib/llvm/lib/CodeGen/AsmPrinter/AddressPool.h
@@ -51,8 +51,14 @@ public:
void resetUsedFlag() { HasBeenUsed = false; }
+ MCSymbol *getLabel() { return AddressTableBaseSym; }
+ void setLabel(MCSymbol *Sym) { AddressTableBaseSym = Sym; }
+
private:
void emitHeader(AsmPrinter &Asm, MCSection *Section);
+
+ /// Symbol designates the start of the contribution to the address table.
+ MCSymbol *AddressTableBaseSym = nullptr;
};
} // end namespace llvm
diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/contrib/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
index 9bbc77b3056b..7070451e3330 100644
--- a/contrib/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/contrib/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -12,10 +12,10 @@
//===----------------------------------------------------------------------===//
#include "llvm/CodeGen/AsmPrinter.h"
-#include "AsmPrinterHandler.h"
#include "CodeViewDebug.h"
#include "DwarfDebug.h"
#include "DwarfException.h"
+#include "WasmException.h"
#include "WinCFGuard.h"
#include "WinException.h"
#include "llvm/ADT/APFloat.h"
@@ -32,8 +32,10 @@
#include "llvm/Analysis/ConstantFolding.h"
#include "llvm/Analysis/EHPersonalities.h"
#include "llvm/Analysis/OptimizationRemarkEmitter.h"
+#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"
@@ -52,6 +54,7 @@
#include "llvm/CodeGen/MachineModuleInfoImpls.h"
#include "llvm/CodeGen/MachineOperand.h"
#include "llvm/CodeGen/MachineOptimizationRemarkEmitter.h"
+#include "llvm/CodeGen/StackMaps.h"
#include "llvm/CodeGen/TargetFrameLowering.h"
#include "llvm/CodeGen/TargetInstrInfo.h"
#include "llvm/CodeGen/TargetLowering.h"
@@ -260,7 +263,7 @@ bool AsmPrinter::doInitialization(Module &M) {
// use the directive, where it would need the same conditionalization
// anyway.
const Triple &Target = TM.getTargetTriple();
- OutStreamer->EmitVersionForTarget(Target);
+ OutStreamer->EmitVersionForTarget(Target, M.getSDKVersion());
// Allow the target to emit any magic that it wants at the start of the file.
EmitStartOfAsmFile(M);
@@ -355,7 +358,7 @@ bool AsmPrinter::doInitialization(Module &M) {
}
break;
case ExceptionHandling::Wasm:
- // TODO to prevent warning
+ ES = new WasmException(this);
break;
}
if (ES)
@@ -363,7 +366,7 @@ bool AsmPrinter::doInitialization(Module &M) {
DWARFGroupName, DWARFGroupDescription));
if (mdconst::extract_or_null<ConstantInt>(
- MMI->getModule()->getModuleFlag("cfguard")))
+ MMI->getModule()->getModuleFlag("cfguardtable")))
Handlers.push_back(HandlerInfo(new WinCFGuard(this), CFGuardName,
CFGuardDescription, DWARFGroupName,
DWARFGroupDescription));
@@ -627,8 +630,7 @@ void AsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) {
///
/// \p Value - The value to emit.
/// \p Size - The size of the integer (in bytes) to emit.
-void AsmPrinter::EmitDebugThreadLocal(const MCExpr *Value,
- unsigned Size) const {
+void AsmPrinter::EmitDebugValue(const MCExpr *Value, unsigned Size) const {
OutStreamer->EmitValue(Value, Size);
}
@@ -749,18 +751,30 @@ static bool emitComments(const MachineInstr &MI, raw_ostream &CommentOS,
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, MMO, FI)) {
- if (MFI.isSpillSlotObjectIndex(FI)) {
- CommentOS << MMO->getSize() << "-byte Folded Reload";
+ } else if (TII->hasLoadFromStackSlot(MI, Accesses)) {
+ if (auto Size = getSize(Accesses)) {
+ CommentOS << Size << "-byte Folded Reload";
Commented = true;
}
} else if (TII->isStoreToStackSlotPostFE(MI, FI)) {
@@ -769,9 +783,9 @@ static bool emitComments(const MachineInstr &MI, raw_ostream &CommentOS,
CommentOS << MMO->getSize() << "-byte Spill";
Commented = true;
}
- } else if (TII->hasStoreToStackSlot(MI, MMO, FI)) {
- if (MFI.isSpillSlotObjectIndex(FI)) {
- CommentOS << MMO->getSize() << "-byte Folded Spill";
+ } else if (TII->hasStoreToStackSlot(MI, Accesses)) {
+ if (auto Size = getSize(Accesses)) {
+ CommentOS << Size << "-byte Folded Spill";
Commented = true;
}
}
@@ -1066,6 +1080,10 @@ void AsmPrinter::EmitFunctionBody() {
++NumInstsInFunction;
}
+ // If there is a pre-instruction symbol, emit a label for it here.
+ if (MCSymbol *S = MI.getPreInstrSymbol())
+ OutStreamer->EmitLabel(S);
+
if (ShouldPrintDebugScopes) {
for (const HandlerInfo &HI : Handlers) {
NamedRegionTimer T(HI.TimerName, HI.TimerDescription,
@@ -1117,6 +1135,10 @@ void AsmPrinter::EmitFunctionBody() {
break;
}
+ // If there is a post-instruction symbol, emit a label for it here.
+ if (MCSymbol *S = MI.getPostInstrSymbol())
+ OutStreamer->EmitLabel(S);
+
if (ShouldPrintDebugScopes) {
for (const HandlerInfo &HI : Handlers) {
NamedRegionTimer T(HI.TimerName, HI.TimerDescription,
@@ -1394,6 +1416,33 @@ bool AsmPrinter::doFinalization(Module &M) {
}
}
+ if (TM.getTargetTriple().isOSBinFormatCOFF()) {
+ MachineModuleInfoCOFF &MMICOFF =
+ MMI->getObjFileInfo<MachineModuleInfoCOFF>();
+
+ // Output stubs for external and common global variables.
+ MachineModuleInfoCOFF::SymbolListTy Stubs = MMICOFF.GetGVStubList();
+ if (!Stubs.empty()) {
+ const DataLayout &DL = M.getDataLayout();
+
+ for (const auto &Stub : Stubs) {
+ SmallString<256> SectionName = StringRef(".rdata$");
+ SectionName += Stub.first->getName();
+ OutStreamer->SwitchSection(OutContext.getCOFFSection(
+ SectionName,
+ COFF::IMAGE_SCN_CNT_INITIALIZED_DATA | COFF::IMAGE_SCN_MEM_READ |
+ COFF::IMAGE_SCN_LNK_COMDAT,
+ SectionKind::getReadOnly(), Stub.first->getName(),
+ COFF::IMAGE_COMDAT_SELECT_ANY));
+ EmitAlignment(Log2_32(DL.getPointerSize()));
+ OutStreamer->EmitSymbolAttribute(Stub.first, MCSA_Global);
+ OutStreamer->EmitLabel(Stub.first);
+ OutStreamer->EmitSymbolValue(Stub.second.getPointer(),
+ DL.getPointerSize());
+ }
+ }
+ }
+
// Finalize debug and EH information.
for (const HandlerInfo &HI : Handlers) {
NamedRegionTimer T(HI.TimerName, HI.TimerDescription, HI.TimerGroupName,
@@ -1450,6 +1499,9 @@ bool AsmPrinter::doFinalization(Module &M) {
// Emit llvm.ident metadata in an '.ident' directive.
EmitModuleIdents(M);
+ // Emit bytes for llvm.commandline metadata.
+ EmitModuleCommandLines(M);
+
// Emit __morestack address if needed for indirect calls.
if (MMI->usesMorestackAddr()) {
unsigned Align = 1;
@@ -1534,7 +1586,8 @@ bool AsmPrinter::doFinalization(Module &M) {
// Emit address-significance attributes for all globals.
OutStreamer->EmitAddrsig();
for (const GlobalValue &GV : M.global_values())
- if (!GV.isThreadLocal() && !GV.getName().startswith("llvm.") &&
+ if (!GV.use_empty() && !GV.isThreadLocal() &&
+ !GV.hasDLLImportStorageClass() && !GV.getName().startswith("llvm.") &&
!GV.hasAtLeastLocalUnnamedAddr())
OutStreamer->EmitAddrsigSym(getSymbol(&GV));
}
@@ -1958,6 +2011,29 @@ void AsmPrinter::EmitModuleIdents(Module &M) {
}
}
+void AsmPrinter::EmitModuleCommandLines(Module &M) {
+ MCSection *CommandLine = getObjFileLowering().getSectionForCommandLines();
+ if (!CommandLine)
+ return;
+
+ const NamedMDNode *NMD = M.getNamedMetadata("llvm.commandline");
+ if (!NMD || !NMD->getNumOperands())
+ return;
+
+ OutStreamer->PushSection();
+ OutStreamer->SwitchSection(CommandLine);
+ OutStreamer->EmitZeros(1);
+ for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) {
+ const MDNode *N = NMD->getOperand(i);
+ assert(N->getNumOperands() == 1 &&
+ "llvm.commandline metadata entry can have only one operand");
+ const MDString *S = cast<MDString>(N->getOperand(0));
+ OutStreamer->EmitBytes(S->getString());
+ OutStreamer->EmitZeros(1);
+ }
+ OutStreamer->PopSection();
+}
+
//===--------------------------------------------------------------------===//
// Emission and print routines
//
@@ -2927,11 +3003,6 @@ GCMetadataPrinter *AsmPrinter::GetOrCreateGCPrinter(GCStrategy &S) {
if (!S.usesMetadata())
return nullptr;
- assert(!S.useStatepoints() && "statepoints do not currently support custom"
- " stackmap formats, please see the documentation for a description of"
- " the default format. If you really need a custom serialized format,"
- " please file a bug");
-
gcp_map_type &GCMap = getGCMap(GCMetadataPrinters);
gcp_map_type::iterator GCPI = GCMap.find(&S);
if (GCPI != GCMap.end())
@@ -2952,6 +3023,27 @@ GCMetadataPrinter *AsmPrinter::GetOrCreateGCPrinter(GCStrategy &S) {
report_fatal_error("no GCMetadataPrinter registered for GC: " + Twine(Name));
}
+void AsmPrinter::emitStackMaps(StackMaps &SM) {
+ GCModuleInfo *MI = getAnalysisIfAvailable<GCModuleInfo>();
+ assert(MI && "AsmPrinter didn't require GCModuleInfo?");
+ bool NeedsDefault = false;
+ if (MI->begin() == MI->end())
+ // No GC strategy, use the default format.
+ NeedsDefault = true;
+ else
+ for (auto &I : *MI) {
+ if (GCMetadataPrinter *MP = GetOrCreateGCPrinter(*I))
+ if (MP->emitStackMaps(SM, *this))
+ continue;
+ // The strategy doesn't have printer or doesn't emit custom stack maps.
+ // Use the default format.
+ NeedsDefault = true;
+ }
+
+ if (NeedsDefault)
+ SM.serializeToStackMapSection();
+}
+
/// Pin vtable to this file.
AsmPrinterHandler::~AsmPrinterHandler() = default;
diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp b/contrib/llvm/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp
index 605588470670..afce3ad3133b 100644
--- a/contrib/llvm/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp
+++ b/contrib/llvm/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp
@@ -212,6 +212,9 @@ void AsmPrinter::emitCFIInstruction(const MCCFIInstruction &Inst) const {
case MCCFIInstruction::OpWindowSave:
OutStreamer->EmitCFIWindowSave();
break;
+ case MCCFIInstruction::OpNegateRAState:
+ OutStreamer->EmitCFINegateRAState();
+ break;
case MCCFIInstruction::OpSameValue:
OutStreamer->EmitCFISameValue(Inst.getRegister());
break;
diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/AsmPrinterHandler.h b/contrib/llvm/lib/CodeGen/AsmPrinter/AsmPrinterHandler.h
deleted file mode 100644
index f5ac95a20b10..000000000000
--- a/contrib/llvm/lib/CodeGen/AsmPrinter/AsmPrinterHandler.h
+++ /dev/null
@@ -1,74 +0,0 @@
-//===-- lib/CodeGen/AsmPrinter/AsmPrinterHandler.h -------------*- C++ -*--===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file contains a generic interface for AsmPrinter handlers,
-// like debug and EH info emitters.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_LIB_CODEGEN_ASMPRINTER_ASMPRINTERHANDLER_H
-#define LLVM_LIB_CODEGEN_ASMPRINTER_ASMPRINTERHANDLER_H
-
-#include "llvm/Support/DataTypes.h"
-
-namespace llvm {
-
-class AsmPrinter;
-class MachineBasicBlock;
-class MachineFunction;
-class MachineInstr;
-class MCSymbol;
-
-typedef MCSymbol *ExceptionSymbolProvider(AsmPrinter *Asm);
-
-/// Collects and handles AsmPrinter objects required to build debug
-/// or EH information.
-class AsmPrinterHandler {
-public:
- virtual ~AsmPrinterHandler();
-
- /// For symbols that have a size designated (e.g. common symbols),
- /// this tracks that size.
- virtual void setSymbolSize(const MCSymbol *Sym, uint64_t Size) = 0;
-
- /// Emit all sections that should come after the content.
- virtual void endModule() = 0;
-
- /// Gather pre-function debug information.
- /// Every beginFunction(MF) call should be followed by an endFunction(MF)
- /// call.
- virtual void beginFunction(const MachineFunction *MF) = 0;
-
- // Emit any of function marker (like .cfi_endproc). This is called
- // before endFunction and cannot switch sections.
- virtual void markFunctionEnd();
-
- /// Gather post-function debug information.
- /// Please note that some AsmPrinter implementations may not call
- /// beginFunction at all.
- virtual void endFunction(const MachineFunction *MF) = 0;
-
- virtual void beginFragment(const MachineBasicBlock *MBB,
- ExceptionSymbolProvider ESP) {}
- virtual void endFragment() {}
-
- /// Emit target-specific EH funclet machinery.
- virtual void beginFunclet(const MachineBasicBlock &MBB,
- MCSymbol *Sym = nullptr) {}
- virtual void endFunclet() {}
-
- /// Process beginning of an instruction.
- virtual void beginInstruction(const MachineInstr *MI) = 0;
-
- /// Process end of an instruction.
- virtual void endInstruction() = 0;
-};
-} // End of namespace llvm
-
-#endif
diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp b/contrib/llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp
index 4159eb19423a..62103e3107c0 100644
--- a/contrib/llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp
+++ b/contrib/llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp
@@ -71,6 +71,42 @@ static void srcMgrDiagHandler(const SMDiagnostic &Diag, void *diagInfo) {
DiagInfo->DiagHandler(Diag, DiagInfo->DiagContext, LocCookie);
}
+unsigned AsmPrinter::addInlineAsmDiagBuffer(StringRef AsmStr,
+ const MDNode *LocMDNode) const {
+ if (!DiagInfo) {
+ DiagInfo = make_unique<SrcMgrDiagInfo>();
+
+ MCContext &Context = MMI->getContext();
+ Context.setInlineSourceManager(&DiagInfo->SrcMgr);
+
+ LLVMContext &LLVMCtx = MMI->getModule()->getContext();
+ if (LLVMCtx.getInlineAsmDiagnosticHandler()) {
+ DiagInfo->DiagHandler = LLVMCtx.getInlineAsmDiagnosticHandler();
+ DiagInfo->DiagContext = LLVMCtx.getInlineAsmDiagnosticContext();
+ DiagInfo->SrcMgr.setDiagHandler(srcMgrDiagHandler, DiagInfo.get());
+ }
+ }
+
+ SourceMgr &SrcMgr = DiagInfo->SrcMgr;
+
+ std::unique_ptr<MemoryBuffer> Buffer;
+ // The inline asm source manager will outlive AsmStr, so make a copy of the
+ // string for SourceMgr to own.
+ Buffer = MemoryBuffer::getMemBufferCopy(AsmStr, "<inline asm>");
+
+ // Tell SrcMgr about this buffer, it takes ownership of the buffer.
+ unsigned BufNum = SrcMgr.AddNewSourceBuffer(std::move(Buffer), SMLoc());
+
+ // Store LocMDNode in DiagInfo, using BufNum as an identifier.
+ if (LocMDNode) {
+ DiagInfo->LocInfos.resize(BufNum);
+ DiagInfo->LocInfos[BufNum - 1] = LocMDNode;
+ }
+
+ return BufNum;
+}
+
+
/// EmitInlineAsm - Emit a blob of inline asm to the output streamer.
void AsmPrinter::EmitInlineAsm(StringRef Str, const MCSubtargetInfo &STI,
const MCTargetOptions &MCOptions,
@@ -98,39 +134,11 @@ void AsmPrinter::EmitInlineAsm(StringRef Str, const MCSubtargetInfo &STI,
return;
}
- if (!DiagInfo) {
- DiagInfo = make_unique<SrcMgrDiagInfo>();
+ unsigned BufNum = addInlineAsmDiagBuffer(Str, LocMDNode);
+ DiagInfo->SrcMgr.setIncludeDirs(MCOptions.IASSearchPaths);
- MCContext &Context = MMI->getContext();
- Context.setInlineSourceManager(&DiagInfo->SrcMgr);
-
- LLVMContext &LLVMCtx = MMI->getModule()->getContext();
- if (LLVMCtx.getInlineAsmDiagnosticHandler()) {
- DiagInfo->DiagHandler = LLVMCtx.getInlineAsmDiagnosticHandler();
- DiagInfo->DiagContext = LLVMCtx.getInlineAsmDiagnosticContext();
- DiagInfo->SrcMgr.setDiagHandler(srcMgrDiagHandler, DiagInfo.get());
- }
- }
-
- SourceMgr &SrcMgr = DiagInfo->SrcMgr;
- SrcMgr.setIncludeDirs(MCOptions.IASSearchPaths);
-
- std::unique_ptr<MemoryBuffer> Buffer;
- // The inline asm source manager will outlive Str, so make a copy of the
- // string for SourceMgr to own.
- Buffer = MemoryBuffer::getMemBufferCopy(Str, "<inline asm>");
-
- // Tell SrcMgr about this buffer, it takes ownership of the buffer.
- unsigned BufNum = SrcMgr.AddNewSourceBuffer(std::move(Buffer), SMLoc());
-
- // Store LocMDNode in DiagInfo, using BufNum as an identifier.
- if (LocMDNode) {
- DiagInfo->LocInfos.resize(BufNum);
- DiagInfo->LocInfos[BufNum-1] = LocMDNode;
- }
-
- std::unique_ptr<MCAsmParser> Parser(
- createMCAsmParser(SrcMgr, OutContext, *OutStreamer, *MAI, BufNum));
+ std::unique_ptr<MCAsmParser> Parser(createMCAsmParser(
+ DiagInfo->SrcMgr, OutContext, *OutStreamer, *MAI, BufNum));
// Do not use assembler-level information for parsing inline assembly.
OutStreamer->setUseAssemblerInfoForParsing(false);
@@ -148,9 +156,10 @@ void AsmPrinter::EmitInlineAsm(StringRef Str, const MCSubtargetInfo &STI,
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)
- // We need this flag to be able to parse numbers like "0bH"
- Parser->setParsingInlineAsm(true);
+ Parser->getLexer().setLexMasmIntegers(true);
if (MF) {
const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo();
TAP->SetFrameRegister(TRI->getFrameRegister(*MF));
@@ -519,6 +528,44 @@ void AsmPrinter::EmitInlineAsm(const MachineInstr *MI) const {
MCOptions.SanitizeAddress =
MF->getFunction().hasFnAttribute(Attribute::SanitizeAddress);
+ // Emit warnings if we use reserved registers on the clobber list, as
+ // that might give surprising results.
+ std::vector<std::string> RestrRegs;
+ // Start with the first operand descriptor, and iterate over them.
+ for (unsigned I = InlineAsm::MIOp_FirstOperand, NumOps = MI->getNumOperands();
+ I < NumOps; ++I) {
+ const MachineOperand &MO = MI->getOperand(I);
+ if (MO.isImm()) {
+ unsigned Flags = MO.getImm();
+ const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo();
+ if (InlineAsm::getKind(Flags) == InlineAsm::Kind_Clobber &&
+ !TRI->isAsmClobberable(*MF, MI->getOperand(I + 1).getReg())) {
+ RestrRegs.push_back(TRI->getName(MI->getOperand(I + 1).getReg()));
+ }
+ // Skip to one before the next operand descriptor, if it exists.
+ I += InlineAsm::getNumOperandRegisters(Flags);
+ }
+ }
+
+ if (!RestrRegs.empty()) {
+ unsigned BufNum = addInlineAsmDiagBuffer(OS.str(), LocMD);
+ auto &SrcMgr = DiagInfo->SrcMgr;
+ SMLoc Loc = SMLoc::getFromPointer(
+ SrcMgr.getMemoryBuffer(BufNum)->getBuffer().begin());
+
+ std::string Msg = "inline asm clobber list contains reserved registers: ";
+ for (auto I = RestrRegs.begin(), E = RestrRegs.end(); I != E; I++) {
+ if(I != RestrRegs.begin())
+ Msg += ", ";
+ Msg += *I;
+ }
+ std::string Note = "Reserved registers on the clobber list may not be "
+ "preserved across the asm statement, and clobbering them may "
+ "lead to undefined behaviour.";
+ SrcMgr.PrintMessage(Loc, SourceMgr::DK_Warning, Msg);
+ SrcMgr.PrintMessage(Loc, SourceMgr::DK_Note, Note);
+ }
+
EmitInlineAsm(OS.str(), getSubtargetInfo(), MCOptions, LocMD,
MI->getInlineAsmDialect());
diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp b/contrib/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
index 8c5c5478d01a..8cabad4ad312 100644
--- a/contrib/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
+++ b/contrib/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
@@ -31,6 +31,7 @@
#include "llvm/BinaryFormat/Dwarf.h"
#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/CodeGen/LexicalScopes.h"
+#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
@@ -43,6 +44,7 @@
#include "llvm/DebugInfo/CodeView/CodeView.h"
#include "llvm/DebugInfo/CodeView/ContinuationRecordBuilder.h"
#include "llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h"
+#include "llvm/DebugInfo/CodeView/EnumTables.h"
#include "llvm/DebugInfo/CodeView/Line.h"
#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
#include "llvm/DebugInfo/CodeView/TypeDumpVisitor.h"
@@ -72,6 +74,7 @@
#include "llvm/Support/Error.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FormatVariadic.h"
+#include "llvm/Support/Path.h"
#include "llvm/Support/SMLoc.h"
#include "llvm/Support/ScopedPrinter.h"
#include "llvm/Target/TargetLoweringObjectFile.h"
@@ -90,8 +93,20 @@
using namespace llvm;
using namespace llvm::codeview;
-static cl::opt<bool> EmitDebugGlobalHashes("emit-codeview-ghash-section",
- cl::ReallyHidden, cl::init(false));
+static CPUType mapArchToCVCPUType(Triple::ArchType Type) {
+ switch (Type) {
+ case Triple::ArchType::x86:
+ return CPUType::Pentium3;
+ case Triple::ArchType::x86_64:
+ return CPUType::X64;
+ case Triple::ArchType::thumb:
+ return CPUType::Thumb;
+ case Triple::ArchType::aarch64:
+ return CPUType::ARM64;
+ default:
+ report_fatal_error("target architecture doesn't map to a CodeView CPUType");
+ }
+}
CodeViewDebug::CodeViewDebug(AsmPrinter *AP)
: DebugHandlerBase(AP), OS(*Asm->OutStreamer), TypeTable(Allocator) {
@@ -100,11 +115,21 @@ CodeViewDebug::CodeViewDebug(AsmPrinter *AP)
if (!MMI->getModule()->getNamedMetadata("llvm.dbg.cu") ||
!AP->getObjFileLowering().getCOFFDebugSymbolsSection()) {
Asm = nullptr;
+ MMI->setDebugInfoAvailability(false);
return;
}
-
// Tell MMI that we have debug info.
MMI->setDebugInfoAvailability(true);
+
+ TheCPU =
+ mapArchToCVCPUType(Triple(MMI->getModule()->getTargetTriple()).getArch());
+
+ collectGlobalVariableInfo();
+
+ // Check if we should emit type record hashes.
+ ConstantInt *GH = mdconst::extract_or_null<ConstantInt>(
+ MMI->getModule()->getModuleFlag("CodeViewGHash"));
+ EmitDebugGlobalHashes = GH && !GH->isZero();
}
StringRef CodeViewDebug::getFullFilepath(const DIFile *File) {
@@ -116,7 +141,9 @@ StringRef CodeViewDebug::getFullFilepath(const DIFile *File) {
// If this is a Unix-style path, just use it as is. Don't try to canonicalize
// it textually because one of the path components could be a symlink.
- if (!Dir.empty() && Dir[0] == '/') {
+ if (Dir.startswith("/") || Filename.startswith("/")) {
+ if (llvm::sys::path::is_absolute(Filename, llvm::sys::path::Style::posix))
+ return Filename;
Filepath = Dir;
if (Dir.back() != '/')
Filepath += '/';
@@ -337,6 +364,36 @@ TypeIndex CodeViewDebug::getFuncIdForSubprogram(const DISubprogram *SP) {
return recordTypeIndexForDINode(SP, TI);
}
+static bool isTrivial(const DICompositeType *DCTy) {
+ return ((DCTy->getFlags() & DINode::FlagTrivial) == DINode::FlagTrivial);
+}
+
+static FunctionOptions
+getFunctionOptions(const DISubroutineType *Ty,
+ const DICompositeType *ClassTy = nullptr,
+ StringRef SPName = StringRef("")) {
+ FunctionOptions FO = FunctionOptions::None;
+ const DIType *ReturnTy = nullptr;
+ if (auto TypeArray = Ty->getTypeArray()) {
+ if (TypeArray.size())
+ ReturnTy = TypeArray[0].resolve();
+ }
+
+ if (auto *ReturnDCTy = dyn_cast_or_null<DICompositeType>(ReturnTy)) {
+ if (!isTrivial(ReturnDCTy))
+ FO |= FunctionOptions::CxxReturnUdt;
+ }
+
+ // DISubroutineType is unnamed. Use DISubprogram's i.e. SPName in comparison.
+ if (ClassTy && !isTrivial(ClassTy) && SPName == ClassTy->getName()) {
+ FO |= FunctionOptions::Constructor;
+
+ // TODO: put the FunctionOptions::ConstructorWithVirtualBases flag.
+
+ }
+ return FO;
+}
+
TypeIndex CodeViewDebug::getMemberFunctionType(const DISubprogram *SP,
const DICompositeType *Class) {
// Always use the method declaration as the key for the function type. The
@@ -356,8 +413,10 @@ TypeIndex CodeViewDebug::getMemberFunctionType(const DISubprogram *SP,
// member function type.
TypeLoweringScope S(*this);
const bool IsStaticMethod = (SP->getFlags() & DINode::FlagStaticMember) != 0;
+
+ FunctionOptions FO = getFunctionOptions(SP->getType(), Class, SP->getName());
TypeIndex TI = lowerTypeMemberFunction(
- SP->getType(), Class, SP->getThisAdjustment(), IsStaticMethod);
+ SP->getType(), Class, SP->getThisAdjustment(), IsStaticMethod, FO);
return recordTypeIndexForDINode(SP, TI, Class);
}
@@ -508,6 +567,11 @@ void CodeViewDebug::endModule() {
OS.AddComment("String table");
OS.EmitCVStringTableDirective();
+ // Emit S_BUILDINFO, which points to LF_BUILDINFO. Put this in its own symbol
+ // subsection in the generic .debug$S section at the end. There is no
+ // particular reason for this ordering other than to match MSVC.
+ emitBuildInfo();
+
// Emit type information and hashes last, so that any types we translate while
// emitting function info are included.
emitTypeInformation();
@@ -669,30 +733,8 @@ static Version parseVersion(StringRef Name) {
return V;
}
-static CPUType mapArchToCVCPUType(Triple::ArchType Type) {
- switch (Type) {
- case Triple::ArchType::x86:
- return CPUType::Pentium3;
- case Triple::ArchType::x86_64:
- return CPUType::X64;
- case Triple::ArchType::thumb:
- return CPUType::Thumb;
- case Triple::ArchType::aarch64:
- return CPUType::ARM64;
- default:
- report_fatal_error("target architecture doesn't map to a CodeView CPUType");
- }
-}
-
void CodeViewDebug::emitCompilerInformation() {
- MCContext &Context = MMI->getContext();
- MCSymbol *CompilerBegin = Context.createTempSymbol(),
- *CompilerEnd = Context.createTempSymbol();
- OS.AddComment("Record length");
- OS.emitAbsoluteSymbolDiff(CompilerEnd, CompilerBegin, 2);
- OS.EmitLabel(CompilerBegin);
- OS.AddComment("Record kind: S_COMPILE3");
- OS.EmitIntValue(SymbolKind::S_COMPILE3, 2);
+ MCSymbol *CompilerEnd = beginSymbolRecord(SymbolKind::S_COMPILE3);
uint32_t Flags = 0;
NamedMDNode *CUs = MMI->getModule()->getNamedMetadata("llvm.dbg.cu");
@@ -707,9 +749,7 @@ void CodeViewDebug::emitCompilerInformation() {
OS.EmitIntValue(Flags, 4);
OS.AddComment("CPUType");
- CPUType CPU =
- mapArchToCVCPUType(Triple(MMI->getModule()->getTargetTriple()).getArch());
- OS.EmitIntValue(static_cast<uint64_t>(CPU), 2);
+ OS.EmitIntValue(static_cast<uint64_t>(TheCPU), 2);
StringRef CompilerVersion = CU->getProducer();
Version FrontVer = parseVersion(CompilerVersion);
@@ -733,7 +773,48 @@ void CodeViewDebug::emitCompilerInformation() {
OS.AddComment("Null-terminated compiler version string");
emitNullTerminatedSymbolName(OS, CompilerVersion);
- OS.EmitLabel(CompilerEnd);
+ endSymbolRecord(CompilerEnd);
+}
+
+static TypeIndex getStringIdTypeIdx(GlobalTypeTableBuilder &TypeTable,
+ StringRef S) {
+ StringIdRecord SIR(TypeIndex(0x0), S);
+ return TypeTable.writeLeafType(SIR);
+}
+
+void CodeViewDebug::emitBuildInfo() {
+ // First, make LF_BUILDINFO. It's a sequence of strings with various bits of
+ // build info. The known prefix is:
+ // - Absolute path of current directory
+ // - Compiler path
+ // - Main source file path, relative to CWD or absolute
+ // - Type server PDB file
+ // - Canonical compiler command line
+ // If frontend and backend compilation are separated (think llc or LTO), it's
+ // not clear if the compiler path should refer to the executable for the
+ // frontend or the backend. Leave it blank for now.
+ TypeIndex BuildInfoArgs[BuildInfoRecord::MaxArgs] = {};
+ NamedMDNode *CUs = MMI->getModule()->getNamedMetadata("llvm.dbg.cu");
+ const MDNode *Node = *CUs->operands().begin(); // FIXME: Multiple CUs.
+ const auto *CU = cast<DICompileUnit>(Node);
+ const DIFile *MainSourceFile = CU->getFile();
+ BuildInfoArgs[BuildInfoRecord::CurrentDirectory] =
+ getStringIdTypeIdx(TypeTable, MainSourceFile->getDirectory());
+ BuildInfoArgs[BuildInfoRecord::SourceFile] =
+ getStringIdTypeIdx(TypeTable, MainSourceFile->getFilename());
+ // FIXME: Path to compiler and command line. PDB is intentionally blank unless
+ // we implement /Zi type servers.
+ BuildInfoRecord BIR(BuildInfoArgs);
+ TypeIndex BuildInfoIndex = TypeTable.writeLeafType(BIR);
+
+ // Make a new .debug$S subsection for the S_BUILDINFO record, which points
+ // from the module symbols into the type stream.
+ MCSymbol *BISubsecEnd = beginCVSubsection(DebugSubsectionKind::Symbols);
+ MCSymbol *BIEnd = beginSymbolRecord(SymbolKind::S_BUILDINFO);
+ OS.AddComment("LF_BUILDINFO index");
+ OS.EmitIntValue(BuildInfoIndex.getIndex(), 4);
+ endSymbolRecord(BIEnd);
+ endCVSubsection(BISubsecEnd);
}
void CodeViewDebug::emitInlineeLinesSubsection() {
@@ -773,18 +854,11 @@ void CodeViewDebug::emitInlineeLinesSubsection() {
void CodeViewDebug::emitInlinedCallSite(const FunctionInfo &FI,
const DILocation *InlinedAt,
const InlineSite &Site) {
- MCSymbol *InlineBegin = MMI->getContext().createTempSymbol(),
- *InlineEnd = MMI->getContext().createTempSymbol();
-
assert(TypeIndices.count({Site.Inlinee, nullptr}));
TypeIndex InlineeIdx = TypeIndices[{Site.Inlinee, nullptr}];
// SymbolRecord
- OS.AddComment("Record length");
- OS.emitAbsoluteSymbolDiff(InlineEnd, InlineBegin, 2); // RecordLength
- OS.EmitLabel(InlineBegin);
- OS.AddComment("Record kind: S_INLINESITE");
- OS.EmitIntValue(SymbolKind::S_INLINESITE, 2); // RecordKind
+ MCSymbol *InlineEnd = beginSymbolRecord(SymbolKind::S_INLINESITE);
OS.AddComment("PtrParent");
OS.EmitIntValue(0, 4);
@@ -799,9 +873,9 @@ void CodeViewDebug::emitInlinedCallSite(const FunctionInfo &FI,
OS.EmitCVInlineLinetableDirective(Site.SiteFuncId, FileId, StartLineNum,
FI.Begin, FI.End);
- OS.EmitLabel(InlineEnd);
+ endSymbolRecord(InlineEnd);
- emitLocalVariableList(Site.InlinedLocals);
+ emitLocalVariableList(FI, Site.InlinedLocals);
// Recurse on child inlined call sites before closing the scope.
for (const DILocation *ChildSite : Site.ChildSites) {
@@ -812,10 +886,7 @@ void CodeViewDebug::emitInlinedCallSite(const FunctionInfo &FI,
}
// Close the scope.
- OS.AddComment("Record length");
- OS.EmitIntValue(2, 2); // RecordLength
- OS.AddComment("Record kind: S_INLINESITE_END");
- OS.EmitIntValue(SymbolKind::S_INLINESITE_END, 2); // RecordKind
+ emitEndSymbolRecord(SymbolKind::S_INLINESITE_END);
}
void CodeViewDebug::switchToDebugSectionForSymbol(const MCSymbol *GVSym) {
@@ -850,13 +921,7 @@ void CodeViewDebug::emitDebugInfoForThunk(const Function *GV,
MCSymbol *SymbolsEnd = beginCVSubsection(DebugSubsectionKind::Symbols);
// Emit S_THUNK32
- MCSymbol *ThunkRecordBegin = MMI->getContext().createTempSymbol(),
- *ThunkRecordEnd = MMI->getContext().createTempSymbol();
- OS.AddComment("Record length");
- OS.emitAbsoluteSymbolDiff(ThunkRecordEnd, ThunkRecordBegin, 2);
- OS.EmitLabel(ThunkRecordBegin);
- OS.AddComment("Record kind: S_THUNK32");
- OS.EmitIntValue(unsigned(SymbolKind::S_THUNK32), 2);
+ MCSymbol *ThunkRecordEnd = beginSymbolRecord(SymbolKind::S_THUNK32);
OS.AddComment("PtrParent");
OS.EmitIntValue(0, 4);
OS.AddComment("PtrEnd");
@@ -874,17 +939,13 @@ void CodeViewDebug::emitDebugInfoForThunk(const Function *GV,
OS.AddComment("Function name");
emitNullTerminatedSymbolName(OS, FuncName);
// Additional fields specific to the thunk ordinal would go here.
- OS.EmitLabel(ThunkRecordEnd);
+ endSymbolRecord(ThunkRecordEnd);
// Local variables/inlined routines are purposely omitted here. The point of
// marking this as a thunk is so Visual Studio will NOT stop in this routine.
// Emit S_PROC_ID_END
- const unsigned RecordLengthForSymbolEnd = 2;
- OS.AddComment("Record length");
- OS.EmitIntValue(RecordLengthForSymbolEnd, 2);
- OS.AddComment("Record kind: S_PROC_ID_END");
- OS.EmitIntValue(unsigned(SymbolKind::S_PROC_ID_END), 2);
+ emitEndSymbolRecord(SymbolKind::S_PROC_ID_END);
endCVSubsection(SymbolsEnd);
}
@@ -927,19 +988,9 @@ void CodeViewDebug::emitDebugInfoForFunction(const Function *GV,
OS.AddComment("Symbol subsection for " + Twine(FuncName));
MCSymbol *SymbolsEnd = beginCVSubsection(DebugSubsectionKind::Symbols);
{
- MCSymbol *ProcRecordBegin = MMI->getContext().createTempSymbol(),
- *ProcRecordEnd = MMI->getContext().createTempSymbol();
- OS.AddComment("Record length");
- OS.emitAbsoluteSymbolDiff(ProcRecordEnd, ProcRecordBegin, 2);
- OS.EmitLabel(ProcRecordBegin);
-
- if (GV->hasLocalLinkage()) {
- OS.AddComment("Record kind: S_LPROC32_ID");
- OS.EmitIntValue(unsigned(SymbolKind::S_LPROC32_ID), 2);
- } else {
- OS.AddComment("Record kind: S_GPROC32_ID");
- OS.EmitIntValue(unsigned(SymbolKind::S_GPROC32_ID), 2);
- }
+ SymbolKind ProcKind = GV->hasLocalLinkage() ? SymbolKind::S_LPROC32_ID
+ : SymbolKind::S_GPROC32_ID;
+ MCSymbol *ProcRecordEnd = beginSymbolRecord(ProcKind);
// These fields are filled in by tools like CVPACK which run after the fact.
OS.AddComment("PtrParent");
@@ -968,9 +1019,28 @@ void CodeViewDebug::emitDebugInfoForFunction(const Function *GV,
OS.AddComment("Function name");
// Truncate the name so we won't overflow the record length field.
emitNullTerminatedSymbolName(OS, FuncName);
- OS.EmitLabel(ProcRecordEnd);
+ endSymbolRecord(ProcRecordEnd);
- emitLocalVariableList(FI.Locals);
+ MCSymbol *FrameProcEnd = beginSymbolRecord(SymbolKind::S_FRAMEPROC);
+ // Subtract out the CSR size since MSVC excludes that and we include it.
+ OS.AddComment("FrameSize");
+ OS.EmitIntValue(FI.FrameSize - FI.CSRSize, 4);
+ OS.AddComment("Padding");
+ OS.EmitIntValue(0, 4);
+ OS.AddComment("Offset of padding");
+ OS.EmitIntValue(0, 4);
+ OS.AddComment("Bytes of callee saved registers");
+ OS.EmitIntValue(FI.CSRSize, 4);
+ OS.AddComment("Exception handler offset");
+ OS.EmitIntValue(0, 4);
+ OS.AddComment("Exception handler section");
+ OS.EmitIntValue(0, 2);
+ OS.AddComment("Flags (defines frame register)");
+ OS.EmitIntValue(uint32_t(FI.FrameProcOpts), 4);
+ endSymbolRecord(FrameProcEnd);
+
+ emitLocalVariableList(FI, FI.Locals);
+ emitGlobalVariableList(FI.Globals);
emitLexicalBlockList(FI.ChildBlocks, FI);
// Emit inlined call site information. Only emit functions inlined directly
@@ -986,13 +1056,7 @@ void CodeViewDebug::emitDebugInfoForFunction(const Function *GV,
for (auto Annot : FI.Annotations) {
MCSymbol *Label = Annot.first;
MDTuple *Strs = cast<MDTuple>(Annot.second);
- MCSymbol *AnnotBegin = MMI->getContext().createTempSymbol(),
- *AnnotEnd = MMI->getContext().createTempSymbol();
- OS.AddComment("Record length");
- OS.emitAbsoluteSymbolDiff(AnnotEnd, AnnotBegin, 2);
- OS.EmitLabel(AnnotBegin);
- OS.AddComment("Record kind: S_ANNOTATION");
- OS.EmitIntValue(SymbolKind::S_ANNOTATION, 2);
+ MCSymbol *AnnotEnd = beginSymbolRecord(SymbolKind::S_ANNOTATION);
OS.EmitCOFFSecRel32(Label, /*Offset=*/0);
// FIXME: Make sure we don't overflow the max record size.
OS.EmitCOFFSectionIndex(Label);
@@ -1004,17 +1068,14 @@ void CodeViewDebug::emitDebugInfoForFunction(const Function *GV,
assert(Str.data()[Str.size()] == '\0' && "non-nullterminated MDString");
OS.EmitBytes(StringRef(Str.data(), Str.size() + 1));
}
- OS.EmitLabel(AnnotEnd);
+ endSymbolRecord(AnnotEnd);
}
if (SP != nullptr)
emitDebugInfoForUDTs(LocalUDTs);
// We're done with this function.
- OS.AddComment("Record length");
- OS.EmitIntValue(0x0002, 2);
- OS.AddComment("Record kind: S_PROC_ID_END");
- OS.EmitIntValue(unsigned(SymbolKind::S_PROC_ID_END), 2);
+ emitEndSymbolRecord(SymbolKind::S_PROC_ID_END);
}
endCVSubsection(SymbolsEnd);
@@ -1034,21 +1095,8 @@ CodeViewDebug::createDefRangeMem(uint16_t CVRegister, int Offset) {
return DR;
}
-CodeViewDebug::LocalVarDefRange
-CodeViewDebug::createDefRangeGeneral(uint16_t CVRegister, bool InMemory,
- int Offset, bool IsSubfield,
- uint16_t StructOffset) {
- LocalVarDefRange DR;
- DR.InMemory = InMemory;
- DR.DataOffset = Offset;
- DR.IsSubfield = IsSubfield;
- DR.StructOffset = StructOffset;
- DR.CVRegister = CVRegister;
- return DR;
-}
-
void CodeViewDebug::collectVariableInfoFromMFTable(
- DenseSet<InlinedVariable> &Processed) {
+ DenseSet<InlinedEntity> &Processed) {
const MachineFunction &MF = *Asm->MF;
const TargetSubtargetInfo &TSI = MF.getSubtarget();
const TargetFrameLowering *TFI = TSI.getFrameLowering();
@@ -1060,7 +1108,7 @@ void CodeViewDebug::collectVariableInfoFromMFTable(
assert(VI.Var->isValidLocationForIntrinsic(VI.Loc) &&
"Expected inlined-at fields to agree");
- Processed.insert(InlinedVariable(VI.Var, VI.Loc->getInlinedAt()));
+ Processed.insert(InlinedEntity(VI.Var, VI.Loc->getInlinedAt()));
LexicalScope *Scope = LScopes.findLexicalScope(VI.Loc);
// If variable scope is not found then skip this variable.
@@ -1196,15 +1244,15 @@ void CodeViewDebug::calculateRanges(
}
void CodeViewDebug::collectVariableInfo(const DISubprogram *SP) {
- DenseSet<InlinedVariable> Processed;
+ DenseSet<InlinedEntity> Processed;
// Grab the variable info that was squirreled away in the MMI side-table.
collectVariableInfoFromMFTable(Processed);
for (const auto &I : DbgValues) {
- InlinedVariable IV = I.first;
+ InlinedEntity IV = I.first;
if (Processed.count(IV))
continue;
- const DILocalVariable *DIVar = IV.first;
+ const DILocalVariable *DIVar = cast<DILocalVariable>(IV.first);
const DILocation *InlinedAt = IV.second;
// Instruction ranges, specifying where IV is accessible.
@@ -1228,6 +1276,9 @@ void CodeViewDebug::collectVariableInfo(const DISubprogram *SP) {
}
void CodeViewDebug::beginFunctionImpl(const MachineFunction *MF) {
+ const TargetSubtargetInfo &TSI = MF->getSubtarget();
+ const TargetRegisterInfo *TRI = TSI.getRegisterInfo();
+ const MachineFrameInfo &MFI = MF->getFrameInfo();
const Function &GV = MF->getFunction();
auto Insertion = FnDebugInfo.insert({&GV, llvm::make_unique<FunctionInfo>()});
assert(Insertion.second && "function already has info");
@@ -1235,6 +1286,66 @@ void CodeViewDebug::beginFunctionImpl(const MachineFunction *MF) {
CurFn->FuncId = NextFuncId++;
CurFn->Begin = Asm->getFunctionBegin();
+ // The S_FRAMEPROC record reports the stack size, and how many bytes of
+ // callee-saved registers were used. For targets that don't use a PUSH
+ // instruction (AArch64), this will be zero.
+ CurFn->CSRSize = MFI.getCVBytesOfCalleeSavedRegisters();
+ CurFn->FrameSize = MFI.getStackSize();
+ CurFn->OffsetAdjustment = MFI.getOffsetAdjustment();
+ CurFn->HasStackRealignment = TRI->needsStackRealignment(*MF);
+
+ // For this function S_FRAMEPROC record, figure out which codeview register
+ // will be the frame pointer.
+ CurFn->EncodedParamFramePtrReg = EncodedFramePtrReg::None; // None.
+ CurFn->EncodedLocalFramePtrReg = EncodedFramePtrReg::None; // None.
+ if (CurFn->FrameSize > 0) {
+ if (!TSI.getFrameLowering()->hasFP(*MF)) {
+ CurFn->EncodedLocalFramePtrReg = EncodedFramePtrReg::StackPtr;
+ CurFn->EncodedParamFramePtrReg = EncodedFramePtrReg::StackPtr;
+ } else {
+ // If there is an FP, parameters are always relative to it.
+ CurFn->EncodedParamFramePtrReg = EncodedFramePtrReg::FramePtr;
+ if (CurFn->HasStackRealignment) {
+ // If the stack needs realignment, locals are relative to SP or VFRAME.
+ CurFn->EncodedLocalFramePtrReg = EncodedFramePtrReg::StackPtr;
+ } else {
+ // Otherwise, locals are relative to EBP, and we probably have VLAs or
+ // other stack adjustments.
+ CurFn->EncodedLocalFramePtrReg = EncodedFramePtrReg::FramePtr;
+ }
+ }
+ }
+
+ // Compute other frame procedure options.
+ FrameProcedureOptions FPO = FrameProcedureOptions::None;
+ if (MFI.hasVarSizedObjects())
+ FPO |= FrameProcedureOptions::HasAlloca;
+ if (MF->exposesReturnsTwice())
+ FPO |= FrameProcedureOptions::HasSetJmp;
+ // FIXME: Set HasLongJmp if we ever track that info.
+ if (MF->hasInlineAsm())
+ FPO |= FrameProcedureOptions::HasInlineAssembly;
+ if (GV.hasPersonalityFn()) {
+ if (isAsynchronousEHPersonality(
+ classifyEHPersonality(GV.getPersonalityFn())))
+ FPO |= FrameProcedureOptions::HasStructuredExceptionHandling;
+ else
+ FPO |= FrameProcedureOptions::HasExceptionHandling;
+ }
+ if (GV.hasFnAttribute(Attribute::InlineHint))
+ FPO |= FrameProcedureOptions::MarkedInline;
+ if (GV.hasFnAttribute(Attribute::Naked))
+ FPO |= FrameProcedureOptions::Naked;
+ if (MFI.hasStackProtectorIndex())
+ 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))
+ FPO |= FrameProcedureOptions::OptimizedForSpeed;
+ // FIXME: Set GuardCfg when it is implemented.
+ CurFn->FrameProcOpts = FPO;
+
OS.EmitCVFuncIdDirective(CurFn->FuncId);
// Find the end of the function prolog. First known non-DBG_VALUE and
@@ -1358,6 +1469,8 @@ TypeIndex CodeViewDebug::lowerType(const DIType *Ty, const DIType *ClassTy) {
case dwarf::DW_TAG_union_type:
return lowerTypeUnion(cast<DICompositeType>(Ty));
case dwarf::DW_TAG_unspecified_type:
+ if (Ty->getName() == "decltype(nullptr)")
+ return TypeIndex::NullptrT();
return TypeIndex::None();
default:
// Use the null type index.
@@ -1552,6 +1665,9 @@ TypeIndex CodeViewDebug::lowerTypePointer(const DIDerivedType *Ty,
break;
}
+ if (Ty->isObjectPointer())
+ PO |= PointerOptions::Const;
+
PointerRecord PR(PointeeTI, PK, PM, PO, Ty->getSizeInBits() / 8);
return TypeTable.writeLeafType(PR);
}
@@ -1702,49 +1818,54 @@ TypeIndex CodeViewDebug::lowerTypeFunction(const DISubroutineType *Ty) {
CallingConvention CC = dwarfCCToCodeView(Ty->getCC());
- ProcedureRecord Procedure(ReturnTypeIndex, CC, FunctionOptions::None,
- ArgTypeIndices.size(), ArgListIndex);
+ FunctionOptions FO = getFunctionOptions(Ty);
+ ProcedureRecord Procedure(ReturnTypeIndex, CC, FO, ArgTypeIndices.size(),
+ ArgListIndex);
return TypeTable.writeLeafType(Procedure);
}
TypeIndex CodeViewDebug::lowerTypeMemberFunction(const DISubroutineType *Ty,
const DIType *ClassTy,
int ThisAdjustment,
- bool IsStaticMethod) {
+ bool IsStaticMethod,
+ FunctionOptions FO) {
// Lower the containing class type.
TypeIndex ClassType = getTypeIndex(ClassTy);
- SmallVector<TypeIndex, 8> ReturnAndArgTypeIndices;
- for (DITypeRef ArgTypeRef : Ty->getTypeArray())
- ReturnAndArgTypeIndices.push_back(getTypeIndex(ArgTypeRef));
+ DITypeRefArray ReturnAndArgs = Ty->getTypeArray();
- // MSVC uses type none for variadic argument.
- if (ReturnAndArgTypeIndices.size() > 1 &&
- ReturnAndArgTypeIndices.back() == TypeIndex::Void()) {
- ReturnAndArgTypeIndices.back() = TypeIndex::None();
- }
- TypeIndex ReturnTypeIndex = TypeIndex::Void();
- ArrayRef<TypeIndex> ArgTypeIndices = None;
- if (!ReturnAndArgTypeIndices.empty()) {
- auto ReturnAndArgTypesRef = makeArrayRef(ReturnAndArgTypeIndices);
- ReturnTypeIndex = ReturnAndArgTypesRef.front();
- ArgTypeIndices = ReturnAndArgTypesRef.drop_front();
- }
+ unsigned Index = 0;
+ SmallVector<TypeIndex, 8> ArgTypeIndices;
+ TypeIndex 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
+ // the arguments.
TypeIndex ThisTypeIndex;
- if (!IsStaticMethod && !ArgTypeIndices.empty()) {
- ThisTypeIndex = ArgTypeIndices.front();
- ArgTypeIndices = ArgTypeIndices.drop_front();
+ if (!IsStaticMethod && ReturnAndArgs.size() > Index) {
+ if (const DIDerivedType *PtrTy =
+ dyn_cast_or_null<DIDerivedType>(ReturnAndArgs[Index].resolve())) {
+ if (PtrTy->getTag() == dwarf::DW_TAG_pointer_type) {
+ ThisTypeIndex = getTypeIndexForThisPtr(PtrTy, Ty);
+ Index++;
+ }
+ }
}
+ while (Index < ReturnAndArgs.size())
+ ArgTypeIndices.push_back(getTypeIndex(ReturnAndArgs[Index++]));
+
+ // MSVC uses type none for variadic argument.
+ if (!ArgTypeIndices.empty() && ArgTypeIndices.back() == TypeIndex::Void())
+ ArgTypeIndices.back() = TypeIndex::None();
+
ArgListRecord ArgListRec(TypeRecordKind::ArgList, ArgTypeIndices);
TypeIndex ArgListIndex = TypeTable.writeLeafType(ArgListRec);
CallingConvention CC = dwarfCCToCodeView(Ty->getCC());
- // TODO: Need to use the correct values for FunctionOptions.
- MemberFunctionRecord MFR(ReturnTypeIndex, ClassType, ThisTypeIndex, CC,
- FunctionOptions::None, ArgTypeIndices.size(),
- ArgListIndex, ThisAdjustment);
+ MemberFunctionRecord MFR(ReturnTypeIndex, ClassType, ThisTypeIndex, CC, FO,
+ ArgTypeIndices.size(), ArgListIndex, ThisAdjustment);
return TypeTable.writeLeafType(MFR);
}
@@ -1825,12 +1946,20 @@ static ClassOptions getCommonClassOptions(const DICompositeType *Ty) {
if (ImmediateScope && isa<DICompositeType>(ImmediateScope))
CO |= ClassOptions::Nested;
- // Put the Scoped flag on function-local types.
- for (const DIScope *Scope = ImmediateScope; Scope != nullptr;
- Scope = Scope->getScope().resolve()) {
- if (isa<DISubprogram>(Scope)) {
+ // Put the Scoped flag on function-local types. MSVC puts this flag for enum
+ // type only when it has an immediate function scope. Clang never puts enums
+ // inside DILexicalBlock scopes. Enum types, as generated by clang, are
+ // always in function, class, or file scopes.
+ if (Ty->getTag() == dwarf::DW_TAG_enumeration_type) {
+ if (ImmediateScope && isa<DISubprogram>(ImmediateScope))
CO |= ClassOptions::Scoped;
- break;
+ } else {
+ for (const DIScope *Scope = ImmediateScope; Scope != nullptr;
+ Scope = Scope->getScope().resolve()) {
+ if (isa<DISubprogram>(Scope)) {
+ CO |= ClassOptions::Scoped;
+ break;
+ }
}
}
@@ -1930,6 +2059,7 @@ void CodeViewDebug::clear() {
GlobalUDTs.clear();
TypeIndices.clear();
CompleteTypeIndices.clear();
+ ScopeGlobals.clear();
}
void CodeViewDebug::collectMemberInfo(ClassInfo &Info,
@@ -2275,6 +2405,32 @@ TypeIndex CodeViewDebug::getTypeIndex(DITypeRef TypeRef, DITypeRef ClassTyRef) {
return recordTypeIndexForDINode(Ty, TI, ClassTy);
}
+codeview::TypeIndex
+CodeViewDebug::getTypeIndexForThisPtr(const DIDerivedType *PtrTy,
+ const DISubroutineType *SubroutineTy) {
+ assert(PtrTy->getTag() == dwarf::DW_TAG_pointer_type &&
+ "this type must be a pointer type");
+
+ PointerOptions Options = PointerOptions::None;
+ if (SubroutineTy->getFlags() & DINode::DIFlags::FlagLValueReference)
+ Options = PointerOptions::LValueRefThisPointer;
+ else if (SubroutineTy->getFlags() & DINode::DIFlags::FlagRValueReference)
+ Options = PointerOptions::RValueRefThisPointer;
+
+ // Check if we've already translated this type. If there is no ref qualifier
+ // on the function then we look up this pointer type with no associated class
+ // so that the TypeIndex for the this pointer can be shared with the type
+ // index for other pointers to this class type. If there is a ref qualifier
+ // then we lookup the pointer using the subroutine as the parent type.
+ auto I = TypeIndices.find({PtrTy, SubroutineTy});
+ if (I != TypeIndices.end())
+ return I->second;
+
+ TypeLoweringScope S(*this);
+ TypeIndex TI = lowerTypePointer(PtrTy, Options);
+ return recordTypeIndexForDINode(PtrTy, TI, SubroutineTy);
+}
+
TypeIndex CodeViewDebug::getTypeIndexForReferenceTo(DITypeRef TypeRef) {
DIType *Ty = TypeRef.resolve();
PointerRecord PR(getTypeIndex(Ty),
@@ -2292,6 +2448,14 @@ TypeIndex CodeViewDebug::getCompleteTypeIndex(DITypeRef TypeRef) {
if (!Ty)
return TypeIndex::Void();
+ // Look through typedefs when getting the complete type index. Call
+ // getTypeIndex on the typdef to ensure that any UDTs are accumulated and are
+ // emitted only once.
+ if (Ty->getTag() == dwarf::DW_TAG_typedef)
+ (void)getTypeIndex(Ty);
+ while (Ty->getTag() == dwarf::DW_TAG_typedef)
+ Ty = cast<DIDerivedType>(Ty)->getBaseType().resolve();
+
// If this is a non-record type, the complete type index is the same as the
// normal type index. Just call getTypeIndex.
switch (Ty->getTag()) {
@@ -2360,35 +2524,40 @@ void CodeViewDebug::emitDeferredCompleteTypes() {
}
}
-void CodeViewDebug::emitLocalVariableList(ArrayRef<LocalVariable> Locals) {
+void CodeViewDebug::emitLocalVariableList(const FunctionInfo &FI,
+ ArrayRef<LocalVariable> Locals) {
// Get the sorted list of parameters and emit them first.
SmallVector<const LocalVariable *, 6> Params;
for (const LocalVariable &L : Locals)
if (L.DIVar->isParameter())
Params.push_back(&L);
- llvm::sort(Params.begin(), Params.end(),
- [](const LocalVariable *L, const LocalVariable *R) {
- return L->DIVar->getArg() < R->DIVar->getArg();
- });
+ llvm::sort(Params, [](const LocalVariable *L, const LocalVariable *R) {
+ return L->DIVar->getArg() < R->DIVar->getArg();
+ });
for (const LocalVariable *L : Params)
- emitLocalVariable(*L);
+ emitLocalVariable(FI, *L);
// Next emit all non-parameters in the order that we found them.
for (const LocalVariable &L : Locals)
if (!L.DIVar->isParameter())
- emitLocalVariable(L);
+ emitLocalVariable(FI, L);
}
-void CodeViewDebug::emitLocalVariable(const LocalVariable &Var) {
- // LocalSym record, see SymbolRecord.h for more info.
- MCSymbol *LocalBegin = MMI->getContext().createTempSymbol(),
- *LocalEnd = MMI->getContext().createTempSymbol();
- OS.AddComment("Record length");
- OS.emitAbsoluteSymbolDiff(LocalEnd, LocalBegin, 2);
- OS.EmitLabel(LocalBegin);
+/// Only call this on endian-specific types like ulittle16_t and little32_t, or
+/// structs composed of them.
+template <typename T>
+static void copyBytesForDefRange(SmallString<20> &BytePrefix,
+ SymbolKind SymKind, const T &DefRangeHeader) {
+ BytePrefix.resize(2 + sizeof(T));
+ ulittle16_t SymKindLE = ulittle16_t(SymKind);
+ memcpy(&BytePrefix[0], &SymKindLE, 2);
+ memcpy(&BytePrefix[2], &DefRangeHeader, sizeof(T));
+}
- OS.AddComment("Record kind: S_LOCAL");
- OS.EmitIntValue(unsigned(SymbolKind::S_LOCAL), 2);
+void CodeViewDebug::emitLocalVariable(const FunctionInfo &FI,
+ const LocalVariable &Var) {
+ // LocalSym record, see SymbolRecord.h for more info.
+ MCSymbol *LocalEnd = beginSymbolRecord(SymbolKind::S_LOCAL);
LocalSymFlags Flags = LocalSymFlags::None;
if (Var.DIVar->isParameter())
@@ -2405,7 +2574,7 @@ void CodeViewDebug::emitLocalVariable(const LocalVariable &Var) {
OS.EmitIntValue(static_cast<uint16_t>(Flags), 2);
// Truncate the name so we won't overflow the record length field.
emitNullTerminatedSymbolName(OS, Var.DIVar->getName());
- OS.EmitLabel(LocalEnd);
+ endSymbolRecord(LocalEnd);
// Calculate the on disk prefix of the appropriate def range record. The
// records and on disk formats are described in SymbolRecords.h. BytePrefix
@@ -2414,45 +2583,53 @@ void CodeViewDebug::emitLocalVariable(const LocalVariable &Var) {
for (const LocalVarDefRange &DefRange : Var.DefRanges) {
BytePrefix.clear();
if (DefRange.InMemory) {
- uint16_t RegRelFlags = 0;
- if (DefRange.IsSubfield) {
- RegRelFlags = DefRangeRegisterRelSym::IsSubfieldFlag |
- (DefRange.StructOffset
- << DefRangeRegisterRelSym::OffsetInParentShift);
+ int Offset = DefRange.DataOffset;
+ unsigned Reg = DefRange.CVRegister;
+
+ // 32-bit x86 call sequences often use PUSH instructions, which disrupt
+ // ESP-relative offsets. Use the virtual frame pointer, VFRAME or $T0,
+ // instead. In frames without stack realignment, $T0 will be the CFA.
+ if (RegisterId(Reg) == RegisterId::ESP) {
+ Reg = unsigned(RegisterId::VFRAME);
+ Offset += FI.OffsetAdjustment;
+ }
+
+ // If we can use the chosen frame pointer for the frame and this isn't a
+ // sliced aggregate, use the smaller S_DEFRANGE_FRAMEPOINTER_REL record.
+ // Otherwise, use S_DEFRANGE_REGISTER_REL.
+ EncodedFramePtrReg EncFP = encodeFramePtrReg(RegisterId(Reg), TheCPU);
+ if (!DefRange.IsSubfield && EncFP != EncodedFramePtrReg::None &&
+ (bool(Flags & LocalSymFlags::IsParameter)
+ ? (EncFP == FI.EncodedParamFramePtrReg)
+ : (EncFP == FI.EncodedLocalFramePtrReg))) {
+ little32_t FPOffset = little32_t(Offset);
+ copyBytesForDefRange(BytePrefix, S_DEFRANGE_FRAMEPOINTER_REL, FPOffset);
+ } else {
+ uint16_t RegRelFlags = 0;
+ if (DefRange.IsSubfield) {
+ RegRelFlags = DefRangeRegisterRelSym::IsSubfieldFlag |
+ (DefRange.StructOffset
+ << DefRangeRegisterRelSym::OffsetInParentShift);
+ }
+ DefRangeRegisterRelSym::Header DRHdr;
+ DRHdr.Register = Reg;
+ DRHdr.Flags = RegRelFlags;
+ DRHdr.BasePointerOffset = Offset;
+ copyBytesForDefRange(BytePrefix, S_DEFRANGE_REGISTER_REL, DRHdr);
}
- DefRangeRegisterRelSym Sym(S_DEFRANGE_REGISTER_REL);
- Sym.Hdr.Register = DefRange.CVRegister;
- Sym.Hdr.Flags = RegRelFlags;
- Sym.Hdr.BasePointerOffset = DefRange.DataOffset;
- ulittle16_t SymKind = ulittle16_t(S_DEFRANGE_REGISTER_REL);
- BytePrefix +=
- StringRef(reinterpret_cast<const char *>(&SymKind), sizeof(SymKind));
- BytePrefix +=
- StringRef(reinterpret_cast<const char *>(&Sym.Hdr), sizeof(Sym.Hdr));
} else {
assert(DefRange.DataOffset == 0 && "unexpected offset into register");
if (DefRange.IsSubfield) {
- // Unclear what matters here.
- DefRangeSubfieldRegisterSym Sym(S_DEFRANGE_SUBFIELD_REGISTER);
- Sym.Hdr.Register = DefRange.CVRegister;
- Sym.Hdr.MayHaveNoName = 0;
- Sym.Hdr.OffsetInParent = DefRange.StructOffset;
-
- ulittle16_t SymKind = ulittle16_t(S_DEFRANGE_SUBFIELD_REGISTER);
- BytePrefix += StringRef(reinterpret_cast<const char *>(&SymKind),
- sizeof(SymKind));
- BytePrefix += StringRef(reinterpret_cast<const char *>(&Sym.Hdr),
- sizeof(Sym.Hdr));
+ DefRangeSubfieldRegisterSym::Header DRHdr;
+ DRHdr.Register = DefRange.CVRegister;
+ DRHdr.MayHaveNoName = 0;
+ DRHdr.OffsetInParent = DefRange.StructOffset;
+ copyBytesForDefRange(BytePrefix, S_DEFRANGE_SUBFIELD_REGISTER, DRHdr);
} else {
- // Unclear what matters here.
- DefRangeRegisterSym Sym(S_DEFRANGE_REGISTER);
- Sym.Hdr.Register = DefRange.CVRegister;
- Sym.Hdr.MayHaveNoName = 0;
- ulittle16_t SymKind = ulittle16_t(S_DEFRANGE_REGISTER);
- BytePrefix += StringRef(reinterpret_cast<const char *>(&SymKind),
- sizeof(SymKind));
- BytePrefix += StringRef(reinterpret_cast<const char *>(&Sym.Hdr),
- sizeof(Sym.Hdr));
+ DefRangeRegisterSym::Header DRHdr;
+ DRHdr.Register = DefRange.CVRegister;
+ DRHdr.MayHaveNoName = 0;
+ copyBytesForDefRange(BytePrefix, S_DEFRANGE_REGISTER, DRHdr);
}
}
OS.EmitCVDefRangeDirective(DefRange.Ranges, BytePrefix);
@@ -2469,15 +2646,7 @@ void CodeViewDebug::emitLexicalBlockList(ArrayRef<LexicalBlock *> Blocks,
/// lexical block scope.
void CodeViewDebug::emitLexicalBlock(const LexicalBlock &Block,
const FunctionInfo& FI) {
- MCSymbol *RecordBegin = MMI->getContext().createTempSymbol(),
- *RecordEnd = MMI->getContext().createTempSymbol();
-
- // Lexical block symbol record.
- OS.AddComment("Record length");
- OS.emitAbsoluteSymbolDiff(RecordEnd, RecordBegin, 2); // Record Length
- OS.EmitLabel(RecordBegin);
- OS.AddComment("Record kind: S_BLOCK32");
- OS.EmitIntValue(SymbolKind::S_BLOCK32, 2); // Record Kind
+ MCSymbol *RecordEnd = beginSymbolRecord(SymbolKind::S_BLOCK32);
OS.AddComment("PtrParent");
OS.EmitIntValue(0, 4); // PtrParent
OS.AddComment("PtrEnd");
@@ -2490,19 +2659,17 @@ void CodeViewDebug::emitLexicalBlock(const LexicalBlock &Block,
OS.EmitCOFFSectionIndex(FI.Begin); // Func Symbol
OS.AddComment("Lexical block name");
emitNullTerminatedSymbolName(OS, Block.Name); // Name
- OS.EmitLabel(RecordEnd);
+ endSymbolRecord(RecordEnd);
// Emit variables local to this lexical block.
- emitLocalVariableList(Block.Locals);
+ emitLocalVariableList(FI, Block.Locals);
+ emitGlobalVariableList(Block.Globals);
// Emit lexical blocks contained within this block.
emitLexicalBlockList(Block.Children, FI);
// Close the lexical block scope.
- OS.AddComment("Record length");
- OS.EmitIntValue(2, 2); // Record Length
- OS.AddComment("Record kind: S_END");
- OS.EmitIntValue(SymbolKind::S_END, 2); // Record Kind
+ emitEndSymbolRecord(SymbolKind::S_END);
}
/// Convenience routine for collecting lexical block information for a list
@@ -2510,9 +2677,10 @@ void CodeViewDebug::emitLexicalBlock(const LexicalBlock &Block,
void CodeViewDebug::collectLexicalBlockInfo(
SmallVectorImpl<LexicalScope *> &Scopes,
SmallVectorImpl<LexicalBlock *> &Blocks,
- SmallVectorImpl<LocalVariable> &Locals) {
+ SmallVectorImpl<LocalVariable> &Locals,
+ SmallVectorImpl<CVGlobalVariable> &Globals) {
for (LexicalScope *Scope : Scopes)
- collectLexicalBlockInfo(*Scope, Blocks, Locals);
+ collectLexicalBlockInfo(*Scope, Blocks, Locals, Globals);
}
/// Populate the lexical blocks and local variable lists of the parent with
@@ -2520,45 +2688,58 @@ void CodeViewDebug::collectLexicalBlockInfo(
void CodeViewDebug::collectLexicalBlockInfo(
LexicalScope &Scope,
SmallVectorImpl<LexicalBlock *> &ParentBlocks,
- SmallVectorImpl<LocalVariable> &ParentLocals) {
+ SmallVectorImpl<LocalVariable> &ParentLocals,
+ SmallVectorImpl<CVGlobalVariable> &ParentGlobals) {
if (Scope.isAbstractScope())
return;
- auto LocalsIter = ScopeVariables.find(&Scope);
- if (LocalsIter == ScopeVariables.end()) {
- // This scope does not contain variables and can be eliminated.
- collectLexicalBlockInfo(Scope.getChildren(), ParentBlocks, ParentLocals);
- return;
- }
- SmallVectorImpl<LocalVariable> &Locals = LocalsIter->second;
-
+ // Gather information about the lexical scope including local variables,
+ // global variables, and address ranges.
+ bool IgnoreScope = false;
+ auto LI = ScopeVariables.find(&Scope);
+ SmallVectorImpl<LocalVariable> *Locals =
+ LI != ScopeVariables.end() ? &LI->second : nullptr;
+ auto GI = ScopeGlobals.find(Scope.getScopeNode());
+ SmallVectorImpl<CVGlobalVariable> *Globals =
+ GI != ScopeGlobals.end() ? GI->second.get() : nullptr;
const DILexicalBlock *DILB = dyn_cast<DILexicalBlock>(Scope.getScopeNode());
- if (!DILB) {
- // This scope is not a lexical block and can be eliminated, but keep any
- // local variables it contains.
- ParentLocals.append(Locals.begin(), Locals.end());
- collectLexicalBlockInfo(Scope.getChildren(), ParentBlocks, ParentLocals);
- return;
- }
-
const SmallVectorImpl<InsnRange> &Ranges = Scope.getRanges();
- if (Ranges.size() != 1 || !getLabelAfterInsn(Ranges.front().second)) {
- // This lexical block scope has too many address ranges to represent in the
- // current CodeView format or does not have a valid address range.
- // Eliminate this lexical scope and promote any locals it contains to the
- // parent scope.
- //
- // For lexical scopes with multiple address ranges you may be tempted to
- // construct a single range covering every instruction where the block is
- // live and everything in between. Unfortunately, Visual Studio only
- // displays variables from the first matching lexical block scope. If the
- // first lexical block contains exception handling code or cold code which
- // is moved to the bottom of the routine creating a single range covering
- // nearly the entire routine, then it will hide all other lexical blocks
- // and the variables they contain.
- //
- ParentLocals.append(Locals.begin(), Locals.end());
- collectLexicalBlockInfo(Scope.getChildren(), ParentBlocks, ParentLocals);
+
+ // Ignore lexical scopes which do not contain variables.
+ if (!Locals && !Globals)
+ IgnoreScope = true;
+
+ // Ignore lexical scopes which are not lexical blocks.
+ if (!DILB)
+ IgnoreScope = true;
+
+ // Ignore scopes which have too many address ranges to represent in the
+ // current CodeView format or do not have a valid address range.
+ //
+ // For lexical scopes with multiple address ranges you may be tempted to
+ // construct a single range covering every instruction where the block is
+ // live and everything in between. Unfortunately, Visual Studio only
+ // displays variables from the first matching lexical block scope. If the
+ // first lexical block contains exception handling code or cold code which
+ // is moved to the bottom of the routine creating a single range covering
+ // nearly the entire routine, then it will hide all other lexical blocks
+ // and the variables they contain.
+ if (Ranges.size() != 1 || !getLabelAfterInsn(Ranges.front().second))
+ IgnoreScope = true;
+
+ if (IgnoreScope) {
+ // This scope can be safely ignored and eliminating it will reduce the
+ // size of the debug information. Be sure to collect any variable and scope
+ // information from the this scope or any of its children and collapse them
+ // into the parent scope.
+ if (Locals)
+ ParentLocals.append(Locals->begin(), Locals->end());
+ if (Globals)
+ ParentGlobals.append(Globals->begin(), Globals->end());
+ collectLexicalBlockInfo(Scope.getChildren(),
+ ParentBlocks,
+ ParentLocals,
+ ParentGlobals);
return;
}
@@ -2569,8 +2750,8 @@ void CodeViewDebug::collectLexicalBlockInfo(
if (!BlockInsertion.second)
return;
- // Create a lexical block containing the local variables and collect the
- // the lexical block information for the children.
+ // Create a lexical block containing the variables and collect the the
+ // lexical block information for the children.
const InsnRange &Range = Ranges.front();
assert(Range.first && Range.second);
LexicalBlock &Block = BlockInsertion.first->second;
@@ -2579,9 +2760,15 @@ void CodeViewDebug::collectLexicalBlockInfo(
assert(Block.Begin && "missing label for scope begin");
assert(Block.End && "missing label for scope end");
Block.Name = DILB->getName();
- Block.Locals = std::move(Locals);
+ if (Locals)
+ Block.Locals = std::move(*Locals);
+ if (Globals)
+ Block.Globals = std::move(*Globals);
ParentBlocks.push_back(&Block);
- collectLexicalBlockInfo(Scope.getChildren(), Block.Children, Block.Locals);
+ collectLexicalBlockInfo(Scope.getChildren(),
+ Block.Children,
+ Block.Locals,
+ Block.Globals);
}
void CodeViewDebug::endFunctionImpl(const MachineFunction *MF) {
@@ -2593,7 +2780,10 @@ void CodeViewDebug::endFunctionImpl(const MachineFunction *MF) {
// Build the lexical block structure to emit for this routine.
if (LexicalScope *CFS = LScopes.getCurrentFunctionScope())
- collectLexicalBlockInfo(*CFS, CurFn->ChildBlocks, CurFn->Locals);
+ collectLexicalBlockInfo(*CFS,
+ CurFn->ChildBlocks,
+ CurFn->Locals,
+ CurFn->Globals);
// Clear the scope and variable information from the map which will not be
// valid after we have finished processing this routine. This also prepares
@@ -2660,30 +2850,57 @@ void CodeViewDebug::endCVSubsection(MCSymbol *EndLabel) {
OS.EmitValueToAlignment(4);
}
+static StringRef getSymbolName(SymbolKind SymKind) {
+ for (const EnumEntry<SymbolKind> &EE : getSymbolTypeNames())
+ if (EE.Value == SymKind)
+ return EE.Name;
+ return "";
+}
+
+MCSymbol *CodeViewDebug::beginSymbolRecord(SymbolKind SymKind) {
+ MCSymbol *BeginLabel = MMI->getContext().createTempSymbol(),
+ *EndLabel = MMI->getContext().createTempSymbol();
+ OS.AddComment("Record length");
+ OS.emitAbsoluteSymbolDiff(EndLabel, BeginLabel, 2);
+ OS.EmitLabel(BeginLabel);
+ if (OS.isVerboseAsm())
+ OS.AddComment("Record kind: " + getSymbolName(SymKind));
+ OS.EmitIntValue(unsigned(SymKind), 2);
+ return EndLabel;
+}
+
+void CodeViewDebug::endSymbolRecord(MCSymbol *SymEnd) {
+ // MSVC does not pad out symbol records to four bytes, but LLVM does to avoid
+ // an extra copy of every symbol record in LLD. This increases object file
+ // size by less than 1% in the clang build, and is compatible with the Visual
+ // C++ linker.
+ OS.EmitValueToAlignment(4);
+ OS.EmitLabel(SymEnd);
+}
+
+void CodeViewDebug::emitEndSymbolRecord(SymbolKind EndKind) {
+ OS.AddComment("Record length");
+ OS.EmitIntValue(2, 2);
+ if (OS.isVerboseAsm())
+ OS.AddComment("Record kind: " + getSymbolName(EndKind));
+ OS.EmitIntValue(unsigned(EndKind), 2); // Record Kind
+}
+
void CodeViewDebug::emitDebugInfoForUDTs(
ArrayRef<std::pair<std::string, const DIType *>> UDTs) {
for (const auto &UDT : UDTs) {
const DIType *T = UDT.second;
assert(shouldEmitUdt(T));
- MCSymbol *UDTRecordBegin = MMI->getContext().createTempSymbol(),
- *UDTRecordEnd = MMI->getContext().createTempSymbol();
- OS.AddComment("Record length");
- OS.emitAbsoluteSymbolDiff(UDTRecordEnd, UDTRecordBegin, 2);
- OS.EmitLabel(UDTRecordBegin);
-
- OS.AddComment("Record kind: S_UDT");
- OS.EmitIntValue(unsigned(SymbolKind::S_UDT), 2);
-
+ MCSymbol *UDTRecordEnd = beginSymbolRecord(SymbolKind::S_UDT);
OS.AddComment("Type");
OS.EmitIntValue(getCompleteTypeIndex(T).getIndex(), 4);
-
emitNullTerminatedSymbolName(OS, UDT.first);
- OS.EmitLabel(UDTRecordEnd);
+ endSymbolRecord(UDTRecordEnd);
}
}
-void CodeViewDebug::emitDebugInfoForGlobals() {
+void CodeViewDebug::collectGlobalVariableInfo() {
DenseMap<const DIGlobalVariableExpression *, const GlobalVariable *>
GlobalMap;
for (const GlobalVariable &GV : MMI->getModule()->globals()) {
@@ -2696,42 +2913,56 @@ void CodeViewDebug::emitDebugInfoForGlobals() {
NamedMDNode *CUs = MMI->getModule()->getNamedMetadata("llvm.dbg.cu");
for (const MDNode *Node : CUs->operands()) {
const auto *CU = cast<DICompileUnit>(Node);
-
- // First, emit all globals that are not in a comdat in a single symbol
- // substream. MSVC doesn't like it if the substream is empty, so only open
- // it if we have at least one global to emit.
- switchToDebugSectionForSymbol(nullptr);
- MCSymbol *EndLabel = nullptr;
for (const auto *GVE : CU->getGlobalVariables()) {
- if (const auto *GV = GlobalMap.lookup(GVE))
- if (!GV->hasComdat() && !GV->isDeclarationForLinker()) {
- if (!EndLabel) {
- OS.AddComment("Symbol subsection for globals");
- EndLabel = beginCVSubsection(DebugSubsectionKind::Symbols);
- }
- // FIXME: emitDebugInfoForGlobal() doesn't handle DIExpressions.
- emitDebugInfoForGlobal(GVE->getVariable(), GV, Asm->getSymbol(GV));
- }
+ 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)) {
+ // Locate a global variable list for this scope, creating one if
+ // necessary.
+ auto Insertion = ScopeGlobals.insert(
+ {Scope, std::unique_ptr<GlobalVariableList>()});
+ if (Insertion.second)
+ Insertion.first->second = llvm::make_unique<GlobalVariableList>();
+ VariableList = Insertion.first->second.get();
+ } else if (GV->hasComdat())
+ // Emit this global variable into a COMDAT section.
+ VariableList = &ComdatVariables;
+ else
+ // Emit this globla variable in a single global symbol section.
+ VariableList = &GlobalVariables;
+ CVGlobalVariable CVGV = {DIGV, GV};
+ VariableList->emplace_back(std::move(CVGV));
}
- if (EndLabel)
- endCVSubsection(EndLabel);
+ }
+}
- // Second, emit each global that is in a comdat into its own .debug$S
- // section along with its own symbol substream.
- for (const auto *GVE : CU->getGlobalVariables()) {
- if (const auto *GV = GlobalMap.lookup(GVE)) {
- if (GV->hasComdat()) {
- MCSymbol *GVSym = Asm->getSymbol(GV);
- OS.AddComment("Symbol subsection for " +
- Twine(GlobalValue::dropLLVMManglingEscape(GV->getName())));
- switchToDebugSectionForSymbol(GVSym);
- EndLabel = beginCVSubsection(DebugSubsectionKind::Symbols);
- // FIXME: emitDebugInfoForGlobal() doesn't handle DIExpressions.
- emitDebugInfoForGlobal(GVE->getVariable(), GV, GVSym);
- endCVSubsection(EndLabel);
- }
- }
- }
+void CodeViewDebug::emitDebugInfoForGlobals() {
+ // First, emit all globals that are not in a comdat in a single symbol
+ // substream. MSVC doesn't like it if the substream is empty, so only open
+ // it if we have at least one global to emit.
+ switchToDebugSectionForSymbol(nullptr);
+ if (!GlobalVariables.empty()) {
+ OS.AddComment("Symbol subsection for globals");
+ MCSymbol *EndLabel = beginCVSubsection(DebugSubsectionKind::Symbols);
+ emitGlobalVariableList(GlobalVariables);
+ endCVSubsection(EndLabel);
+ }
+
+ // 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);
+ OS.AddComment("Symbol subsection for " +
+ Twine(GlobalValue::dropLLVMManglingEscape(CVGV.GV->getName())));
+ switchToDebugSectionForSymbol(GVSym);
+ MCSymbol *EndLabel = beginCVSubsection(DebugSubsectionKind::Symbols);
+ // FIXME: emitDebugInfoForGlobal() doesn't handle DIExpressions.
+ emitDebugInfoForGlobal(CVGV.DIGV, CVGV.GV, GVSym);
+ endCVSubsection(EndLabel);
}
}
@@ -2747,34 +2978,26 @@ 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.
- // FIXME: Thread local data, etc
- MCSymbol *DataBegin = MMI->getContext().createTempSymbol(),
- *DataEnd = MMI->getContext().createTempSymbol();
- const unsigned FixedLengthOfThisRecord = 12;
- OS.AddComment("Record length");
- OS.emitAbsoluteSymbolDiff(DataEnd, DataBegin, 2);
- OS.EmitLabel(DataBegin);
- if (DIGV->isLocalToUnit()) {
- if (GV->isThreadLocal()) {
- OS.AddComment("Record kind: S_LTHREAD32");
- OS.EmitIntValue(unsigned(SymbolKind::S_LTHREAD32), 2);
- } else {
- OS.AddComment("Record kind: S_LDATA32");
- OS.EmitIntValue(unsigned(SymbolKind::S_LDATA32), 2);
- }
- } else {
- if (GV->isThreadLocal()) {
- OS.AddComment("Record kind: S_GTHREAD32");
- OS.EmitIntValue(unsigned(SymbolKind::S_GTHREAD32), 2);
- } else {
- OS.AddComment("Record kind: S_GDATA32");
- OS.EmitIntValue(unsigned(SymbolKind::S_GDATA32), 2);
- }
- }
+ // 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");
@@ -2782,6 +3005,7 @@ void CodeViewDebug::emitDebugInfoForGlobal(const DIGlobalVariable *DIGV,
OS.AddComment("Segment");
OS.EmitCOFFSectionIndex(GVSym);
OS.AddComment("Name");
- emitNullTerminatedSymbolName(OS, DIGV->getName(), FixedLengthOfThisRecord);
- OS.EmitLabel(DataEnd);
+ const unsigned LengthOfDataRecord = 12;
+ emitNullTerminatedSymbolName(OS, DIGV->getName(), LengthOfDataRecord);
+ endSymbolRecord(DataEnd);
}
diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h b/contrib/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h
index 6a0da5f993d0..21557ed1be35 100644
--- a/contrib/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h
+++ b/contrib/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.h
@@ -14,14 +14,14 @@
#ifndef LLVM_LIB_CODEGEN_ASMPRINTER_CODEVIEWDEBUG_H
#define LLVM_LIB_CODEGEN_ASMPRINTER_CODEVIEWDEBUG_H
-#include "DbgValueHistoryCalculator.h"
-#include "DebugHandlerBase.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/SmallVector.h"
+#include "llvm/CodeGen/DbgEntityHistoryCalculator.h"
+#include "llvm/CodeGen/DebugHandlerBase.h"
#include "llvm/DebugInfo/CodeView/CodeView.h"
#include "llvm/DebugInfo/CodeView/GlobalTypeTableBuilder.h"
#include "llvm/DebugInfo/CodeView/TypeIndex.h"
@@ -54,6 +54,12 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDebug : public DebugHandlerBase {
BumpPtrAllocator Allocator;
codeview::GlobalTypeTableBuilder TypeTable;
+ /// Whether to emit type record hashes into .debug$H.
+ bool EmitDebugGlobalHashes = false;
+
+ /// The codeview CPU type used by the translation unit.
+ codeview::CPUType TheCPU;
+
/// Represents the most general definition range.
struct LocalVarDefRange {
/// Indicates that variable data is stored in memory relative to the
@@ -85,10 +91,6 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDebug : public DebugHandlerBase {
};
static LocalVarDefRange createDefRangeMem(uint16_t CVRegister, int Offset);
- static LocalVarDefRange createDefRangeGeneral(uint16_t CVRegister,
- bool InMemory, int Offset,
- bool IsSubfield,
- uint16_t StructOffset);
/// Similar to DbgVariable in DwarfDebug, but not dwarf-specific.
struct LocalVariable {
@@ -97,6 +99,11 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDebug : public DebugHandlerBase {
bool UseReferenceType = false;
};
+ struct CVGlobalVariable {
+ const DIGlobalVariable *DIGV;
+ const GlobalVariable *GV;
+ };
+
struct InlineSite {
SmallVector<LocalVariable, 1> InlinedLocals;
SmallVector<const DILocation *, 1> ChildSites;
@@ -110,6 +117,7 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDebug : public DebugHandlerBase {
// Combines information from DILexicalBlock and LexicalScope.
struct LexicalBlock {
SmallVector<LocalVariable, 1> Locals;
+ SmallVector<CVGlobalVariable, 1> Globals;
SmallVector<LexicalBlock *, 1> Children;
const MCSymbol *Begin;
const MCSymbol *End;
@@ -132,6 +140,7 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDebug : public DebugHandlerBase {
SmallVector<const DILocation *, 1> ChildSites;
SmallVector<LocalVariable, 1> Locals;
+ SmallVector<CVGlobalVariable, 1> Globals;
std::unordered_map<const DILexicalBlockBase*, LexicalBlock> LexicalBlocks;
@@ -144,6 +153,33 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDebug : public DebugHandlerBase {
const MCSymbol *End = nullptr;
unsigned FuncId = 0;
unsigned LastFileId = 0;
+
+ /// Number of bytes allocated in the prologue for all local stack objects.
+ unsigned FrameSize = 0;
+
+ /// Number of bytes of parameters on the stack.
+ unsigned ParamSize = 0;
+
+ /// Number of bytes pushed to save CSRs.
+ unsigned CSRSize = 0;
+
+ /// Adjustment to apply on x86 when using the VFRAME frame pointer.
+ int OffsetAdjustment = 0;
+
+ /// Two-bit value indicating which register is the designated frame pointer
+ /// register for local variables. Included in S_FRAMEPROC.
+ codeview::EncodedFramePtrReg EncodedLocalFramePtrReg =
+ codeview::EncodedFramePtrReg::None;
+
+ /// Two-bit value indicating which register is the designated frame pointer
+ /// register for stack parameters. Included in S_FRAMEPROC.
+ codeview::EncodedFramePtrReg EncodedParamFramePtrReg =
+ codeview::EncodedFramePtrReg::None;
+
+ codeview::FrameProcedureOptions FrameProcOpts;
+
+ bool HasStackRealignment = false;
+
bool HaveLineInfo = false;
};
FunctionInfo *CurFn = nullptr;
@@ -154,6 +190,17 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDebug : public DebugHandlerBase {
// and LexicalBlocks.
DenseMap<const LexicalScope *, SmallVector<LocalVariable, 1>> ScopeVariables;
+ // Map to separate global variables according to the lexical scope they
+ // belong in. A null local scope represents the global scope.
+ typedef SmallVector<CVGlobalVariable, 1> GlobalVariableList;
+ DenseMap<const DIScope*, std::unique_ptr<GlobalVariableList> > ScopeGlobals;
+
+ // Array of global variables which need to be emitted into a COMDAT section.
+ SmallVector<CVGlobalVariable, 1> ComdatVariables;
+
+ // Array of non-COMDAT global variables.
+ SmallVector<CVGlobalVariable, 1> GlobalVariables;
+
/// The set of comdat .debug$S sections that we've seen so far. Each section
/// must start with a magic version number that must only be emitted once.
/// This set tracks which sections we've already opened.
@@ -249,6 +296,8 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDebug : public DebugHandlerBase {
void emitCompilerInformation();
+ void emitBuildInfo();
+
void emitInlineeLinesSubsection();
void emitDebugInfoForThunk(const Function *GV,
@@ -257,13 +306,13 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDebug : public DebugHandlerBase {
void emitDebugInfoForFunction(const Function *GV, FunctionInfo &FI);
- void emitDebugInfoForGlobals();
-
void emitDebugInfoForRetainedTypes();
void
emitDebugInfoForUDTs(ArrayRef<std::pair<std::string, const DIType *>> UDTs);
+ void emitDebugInfoForGlobals();
+ void emitGlobalVariableList(ArrayRef<CVGlobalVariable> Globals);
void emitDebugInfoForGlobal(const DIGlobalVariable *DIGV,
const GlobalVariable *GV, MCSymbol *GVSym);
@@ -271,36 +320,49 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDebug : public DebugHandlerBase {
/// Returns an end label for use with endCVSubsection when the subsection is
/// finished.
MCSymbol *beginCVSubsection(codeview::DebugSubsectionKind Kind);
-
void endCVSubsection(MCSymbol *EndLabel);
+ /// Opens a symbol record of the given kind. Returns an end label for use with
+ /// endSymbolRecord.
+ MCSymbol *beginSymbolRecord(codeview::SymbolKind Kind);
+ void endSymbolRecord(MCSymbol *SymEnd);
+
+ /// Emits an S_END, S_INLINESITE_END, or S_PROC_ID_END record. These records
+ /// are empty, so we emit them with a simpler assembly sequence that doesn't
+ /// involve labels.
+ void emitEndSymbolRecord(codeview::SymbolKind EndKind);
+
void emitInlinedCallSite(const FunctionInfo &FI, const DILocation *InlinedAt,
const InlineSite &Site);
- using InlinedVariable = DbgValueHistoryMap::InlinedVariable;
+ using InlinedEntity = DbgValueHistoryMap::InlinedEntity;
+ void collectGlobalVariableInfo();
void collectVariableInfo(const DISubprogram *SP);
- void collectVariableInfoFromMFTable(DenseSet<InlinedVariable> &Processed);
+ void collectVariableInfoFromMFTable(DenseSet<InlinedEntity> &Processed);
// Construct the lexical block tree for a routine, pruning emptpy lexical
// scopes, and populate it with local variables.
void collectLexicalBlockInfo(SmallVectorImpl<LexicalScope *> &Scopes,
SmallVectorImpl<LexicalBlock *> &Blocks,
- SmallVectorImpl<LocalVariable> &Locals);
+ SmallVectorImpl<LocalVariable> &Locals,
+ SmallVectorImpl<CVGlobalVariable> &Globals);
void collectLexicalBlockInfo(LexicalScope &Scope,
SmallVectorImpl<LexicalBlock *> &ParentBlocks,
- SmallVectorImpl<LocalVariable> &ParentLocals);
+ SmallVectorImpl<LocalVariable> &ParentLocals,
+ SmallVectorImpl<CVGlobalVariable> &ParentGlobals);
/// Records information about a local variable in the appropriate scope. In
/// particular, locals from inlined code live inside the inlining site.
void recordLocalVariable(LocalVariable &&Var, const LexicalScope *LS);
/// Emits local variables in the appropriate order.
- void emitLocalVariableList(ArrayRef<LocalVariable> Locals);
+ void emitLocalVariableList(const FunctionInfo &FI,
+ ArrayRef<LocalVariable> Locals);
/// Emits an S_LOCAL record and its associated defined ranges.
- void emitLocalVariable(const LocalVariable &Var);
+ void emitLocalVariable(const FunctionInfo &FI, const LocalVariable &Var);
/// Emits a sequence of lexical block scopes and their children.
void emitLexicalBlockList(ArrayRef<LexicalBlock *> Blocks,
@@ -314,6 +376,10 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDebug : public DebugHandlerBase {
codeview::TypeIndex getTypeIndex(DITypeRef TypeRef,
DITypeRef ClassTyRef = DITypeRef());
+ codeview::TypeIndex
+ getTypeIndexForThisPtr(const DIDerivedType *PtrTy,
+ const DISubroutineType *SubroutineTy);
+
codeview::TypeIndex getTypeIndexForReferenceTo(DITypeRef TypeRef);
codeview::TypeIndex getMemberFunctionType(const DISubprogram *SP,
@@ -340,10 +406,10 @@ class LLVM_LIBRARY_VISIBILITY CodeViewDebug : public DebugHandlerBase {
codeview::TypeIndex lowerTypeModifier(const DIDerivedType *Ty);
codeview::TypeIndex lowerTypeFunction(const DISubroutineType *Ty);
codeview::TypeIndex lowerTypeVFTableShape(const DIDerivedType *Ty);
- codeview::TypeIndex lowerTypeMemberFunction(const DISubroutineType *Ty,
- const DIType *ClassTy,
- int ThisAdjustment,
- bool IsStaticMethod);
+ codeview::TypeIndex lowerTypeMemberFunction(
+ const DISubroutineType *Ty, const DIType *ClassTy, int ThisAdjustment,
+ bool IsStaticMethod,
+ codeview::FunctionOptions FO = codeview::FunctionOptions::None);
codeview::TypeIndex lowerTypeEnum(const DICompositeType *Ty);
codeview::TypeIndex lowerTypeClass(const DICompositeType *Ty);
codeview::TypeIndex lowerTypeUnion(const DICompositeType *Ty);
diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/DIE.cpp b/contrib/llvm/lib/CodeGen/AsmPrinter/DIE.cpp
index 570424a79c81..e27659494f08 100644
--- a/contrib/llvm/lib/CodeGen/AsmPrinter/DIE.cpp
+++ b/contrib/llvm/lib/CodeGen/AsmPrinter/DIE.cpp
@@ -414,6 +414,8 @@ void DIEInteger::EmitValue(const AsmPrinter *Asm, dwarf::Form Form) const {
case dwarf::DW_FORM_GNU_addr_index:
case dwarf::DW_FORM_ref_udata:
case dwarf::DW_FORM_strx:
+ case dwarf::DW_FORM_addrx:
+ case dwarf::DW_FORM_rnglistx:
case dwarf::DW_FORM_udata:
Asm->EmitULEB128(Integer);
return;
@@ -440,6 +442,8 @@ unsigned DIEInteger::SizeOf(const AsmPrinter *AP, dwarf::Form Form) const {
case dwarf::DW_FORM_GNU_addr_index:
case dwarf::DW_FORM_ref_udata:
case dwarf::DW_FORM_strx:
+ case dwarf::DW_FORM_addrx:
+ case dwarf::DW_FORM_rnglistx:
case dwarf::DW_FORM_udata:
return getULEB128Size(Integer);
case dwarf::DW_FORM_sdata:
@@ -461,7 +465,7 @@ void DIEInteger::print(raw_ostream &O) const {
/// EmitValue - Emit expression value.
///
void DIEExpr::EmitValue(const AsmPrinter *AP, dwarf::Form Form) const {
- AP->EmitDebugThreadLocal(Expr, SizeOf(AP, Form));
+ AP->EmitDebugValue(Expr, SizeOf(AP, Form));
}
/// SizeOf - Determine size of expression value in bytes.
@@ -585,8 +589,7 @@ void DIEString::print(raw_ostream &O) const {
//===----------------------------------------------------------------------===//
void DIEInlineString::EmitValue(const AsmPrinter *AP, dwarf::Form Form) const {
if (Form == dwarf::DW_FORM_string) {
- for (char ch : S)
- AP->emitInt8(ch);
+ AP->OutStreamer->EmitBytes(S);
AP->emitInt8(0);
return;
}
diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/DbgValueHistoryCalculator.cpp b/contrib/llvm/lib/CodeGen/AsmPrinter/DbgEntityHistoryCalculator.cpp
index 25518a339c61..09867822c30a 100644
--- a/contrib/llvm/lib/CodeGen/AsmPrinter/DbgValueHistoryCalculator.cpp
+++ b/contrib/llvm/lib/CodeGen/AsmPrinter/DbgEntityHistoryCalculator.cpp
@@ -1,4 +1,4 @@
-//===- llvm/CodeGen/AsmPrinter/DbgValueHistoryCalculator.cpp --------------===//
+//===- llvm/CodeGen/AsmPrinter/DbgEntityHistoryCalculator.cpp -------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,7 +7,7 @@
//
//===----------------------------------------------------------------------===//
-#include "DbgValueHistoryCalculator.h"
+#include "llvm/CodeGen/DbgEntityHistoryCalculator.h"
#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
@@ -42,7 +42,7 @@ static unsigned isDescribedByReg(const MachineInstr &MI) {
return MI.getOperand(0).isReg() ? MI.getOperand(0).getReg() : 0;
}
-void DbgValueHistoryMap::startInstrRange(InlinedVariable Var,
+void DbgValueHistoryMap::startInstrRange(InlinedEntity Var,
const MachineInstr &MI) {
// Instruction range should start with a DBG_VALUE instruction for the
// variable.
@@ -57,7 +57,7 @@ void DbgValueHistoryMap::startInstrRange(InlinedVariable Var,
Ranges.push_back(std::make_pair(&MI, nullptr));
}
-void DbgValueHistoryMap::endInstrRange(InlinedVariable Var,
+void DbgValueHistoryMap::endInstrRange(InlinedEntity Var,
const MachineInstr &MI) {
auto &Ranges = VarInstrRanges[Var];
// Verify that the current instruction range is not yet closed.
@@ -68,7 +68,7 @@ void DbgValueHistoryMap::endInstrRange(InlinedVariable Var,
Ranges.back().second = &MI;
}
-unsigned DbgValueHistoryMap::getRegisterForVar(InlinedVariable Var) const {
+unsigned DbgValueHistoryMap::getRegisterForVar(InlinedEntity Var) const {
const auto &I = VarInstrRanges.find(Var);
if (I == VarInstrRanges.end())
return 0;
@@ -78,17 +78,22 @@ unsigned DbgValueHistoryMap::getRegisterForVar(InlinedVariable Var) const {
return isDescribedByReg(*Ranges.back().first);
}
+void DbgLabelInstrMap::addInstr(InlinedEntity Label, const MachineInstr &MI) {
+ assert(MI.isDebugLabel() && "not a DBG_LABEL");
+ LabelInstr[Label] = &MI;
+}
+
namespace {
// Maps physreg numbers to the variables they describe.
-using InlinedVariable = DbgValueHistoryMap::InlinedVariable;
-using RegDescribedVarsMap = std::map<unsigned, SmallVector<InlinedVariable, 1>>;
+using InlinedEntity = DbgValueHistoryMap::InlinedEntity;
+using RegDescribedVarsMap = std::map<unsigned, SmallVector<InlinedEntity, 1>>;
} // end anonymous namespace
// Claim that @Var is not described by @RegNo anymore.
static void dropRegDescribedVar(RegDescribedVarsMap &RegVars, unsigned RegNo,
- InlinedVariable Var) {
+ InlinedEntity Var) {
const auto &I = RegVars.find(RegNo);
assert(RegNo != 0U && I != RegVars.end());
auto &VarSet = I->second;
@@ -102,7 +107,7 @@ static void dropRegDescribedVar(RegDescribedVarsMap &RegVars, unsigned RegNo,
// Claim that @Var is now described by @RegNo.
static void addRegDescribedVar(RegDescribedVarsMap &RegVars, unsigned RegNo,
- InlinedVariable Var) {
+ InlinedEntity Var) {
assert(RegNo != 0U);
auto &VarSet = RegVars[RegNo];
assert(!is_contained(VarSet, Var));
@@ -187,9 +192,10 @@ static void collectChangingRegs(const MachineFunction *MF,
}
}
-void llvm::calculateDbgValueHistory(const MachineFunction *MF,
- const TargetRegisterInfo *TRI,
- DbgValueHistoryMap &Result) {
+void llvm::calculateDbgEntityHistory(const MachineFunction *MF,
+ const TargetRegisterInfo *TRI,
+ DbgValueHistoryMap &DbgValues,
+ DbgLabelInstrMap &DbgLabels) {
BitVector ChangingRegs(TRI->getNumRegs());
collectChangingRegs(MF, TRI, ChangingRegs);
@@ -210,14 +216,14 @@ void llvm::calculateDbgValueHistory(const MachineFunction *MF,
// If this is a virtual register, only clobber it since it doesn't
// have aliases.
if (TRI->isVirtualRegister(MO.getReg()))
- clobberRegisterUses(RegVars, MO.getReg(), Result, MI);
+ 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, Result, MI);
+ clobberRegisterUses(RegVars, *AI, DbgValues, MI);
}
} else if (MO.isRegMask()) {
// If this is a register mask operand, clobber all debug values in
@@ -226,7 +232,7 @@ void llvm::calculateDbgValueHistory(const MachineFunction *MF,
// Don't consider SP to be clobbered by register masks.
if (unsigned(I) != SP && TRI->isPhysicalRegister(I) &&
MO.clobbersPhysReg(I)) {
- clobberRegisterUses(RegVars, I, Result, MI);
+ clobberRegisterUses(RegVars, I, DbgValues, MI);
}
}
}
@@ -234,26 +240,34 @@ void llvm::calculateDbgValueHistory(const MachineFunction *MF,
continue;
}
- // Skip DBG_LABEL instructions.
- if (MI.isDebugLabel())
- continue;
-
- assert(MI.getNumOperands() > 1 && "Invalid DBG_VALUE instruction!");
- // Use the base variable (without any DW_OP_piece expressions)
- // as index into History. The full variables including the
- // piece expressions are attached to the MI.
- const DILocalVariable *RawVar = MI.getDebugVariable();
- assert(RawVar->isValidLocationForIntrinsic(MI.getDebugLoc()) &&
- "Expected inlined-at fields to agree");
- InlinedVariable Var(RawVar, MI.getDebugLoc()->getInlinedAt());
-
- if (unsigned PrevReg = Result.getRegisterForVar(Var))
- dropRegDescribedVar(RegVars, PrevReg, Var);
-
- Result.startInstrRange(Var, MI);
-
- if (unsigned NewReg = isDescribedByReg(MI))
- addRegDescribedVar(RegVars, NewReg, Var);
+ if (MI.isDebugValue()) {
+ assert(MI.getNumOperands() > 1 && "Invalid DBG_VALUE instruction!");
+ // Use the base variable (without any DW_OP_piece expressions)
+ // as index into History. The full variables including the
+ // piece expressions are attached to the MI.
+ const DILocalVariable *RawVar = MI.getDebugVariable();
+ assert(RawVar->isValidLocationForIntrinsic(MI.getDebugLoc()) &&
+ "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);
+ } else if (MI.isDebugLabel()) {
+ assert(MI.getNumOperands() == 1 && "Invalid DBG_LABEL instruction!");
+ const DILabel *RawLabel = MI.getDebugLabel();
+ assert(RawLabel->isValidLocationForIntrinsic(MI.getDebugLoc()) &&
+ "Expected inlined-at fields to agree");
+ // When collecting debug information for labels, there is no MCSymbol
+ // generated for it. So, we keep MachineInstr in DbgLabels in order
+ // to query MCSymbol afterward.
+ InlinedEntity L(RawLabel, MI.getDebugLoc()->getInlinedAt());
+ DbgLabels.addInstr(L, MI);
+ }
}
// Make sure locations for register-described variables are valid only
@@ -264,7 +278,7 @@ void llvm::calculateDbgValueHistory(const MachineFunction *MF,
auto CurElem = I++; // CurElem can be erased below.
if (TRI->isVirtualRegister(CurElem->first) ||
ChangingRegs.test(CurElem->first))
- clobberRegisterUses(RegVars, CurElem, Result, MBB.back());
+ clobberRegisterUses(RegVars, CurElem, DbgValues, MBB.back());
}
}
}
@@ -274,10 +288,10 @@ void llvm::calculateDbgValueHistory(const MachineFunction *MF,
LLVM_DUMP_METHOD void DbgValueHistoryMap::dump() const {
dbgs() << "DbgValueHistoryMap:\n";
for (const auto &VarRangePair : *this) {
- const InlinedVariable &Var = VarRangePair.first;
+ const InlinedEntity &Var = VarRangePair.first;
const InstrRanges &Ranges = VarRangePair.second;
- const DILocalVariable *LocalVar = Var.first;
+ const DILocalVariable *LocalVar = cast<DILocalVariable>(Var.first);
const DILocation *Location = Var.second;
dbgs() << " - " << LocalVar->getName() << " at ";
diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/DbgValueHistoryCalculator.h b/contrib/llvm/lib/CodeGen/AsmPrinter/DbgValueHistoryCalculator.h
deleted file mode 100644
index a262cb38b175..000000000000
--- a/contrib/llvm/lib/CodeGen/AsmPrinter/DbgValueHistoryCalculator.h
+++ /dev/null
@@ -1,67 +0,0 @@
-//===- llvm/CodeGen/AsmPrinter/DbgValueHistoryCalculator.h ------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_LIB_CODEGEN_ASMPRINTER_DBGVALUEHISTORYCALCULATOR_H
-#define LLVM_LIB_CODEGEN_ASMPRINTER_DBGVALUEHISTORYCALCULATOR_H
-
-#include "llvm/ADT/MapVector.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/IR/DebugInfoMetadata.h"
-#include <utility>
-
-namespace llvm {
-
-class DILocalVariable;
-class MachineFunction;
-class MachineInstr;
-class TargetRegisterInfo;
-
-// For each user variable, keep a list of instruction ranges where this variable
-// is accessible. The variables are listed in order of appearance.
-class DbgValueHistoryMap {
- // Each instruction range starts with a DBG_VALUE instruction, specifying the
- // location of a variable, which is assumed to be valid until the end of the
- // range. If end is not specified, location is valid until the start
- // instruction of the next instruction range, or until the end of the
- // function.
-public:
- using InstrRange = std::pair<const MachineInstr *, const MachineInstr *>;
- using InstrRanges = SmallVector<InstrRange, 4>;
- using InlinedVariable =
- std::pair<const DILocalVariable *, const DILocation *>;
- using InstrRangesMap = MapVector<InlinedVariable, InstrRanges>;
-
-private:
- InstrRangesMap VarInstrRanges;
-
-public:
- void startInstrRange(InlinedVariable Var, const MachineInstr &MI);
- void endInstrRange(InlinedVariable Var, const MachineInstr &MI);
-
- // Returns register currently describing @Var. If @Var is currently
- // unaccessible or is not described by a register, returns 0.
- unsigned getRegisterForVar(InlinedVariable Var) const;
-
- bool empty() const { return VarInstrRanges.empty(); }
- void clear() { VarInstrRanges.clear(); }
- InstrRangesMap::const_iterator begin() const { return VarInstrRanges.begin(); }
- InstrRangesMap::const_iterator end() const { return VarInstrRanges.end(); }
-
-#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
- LLVM_DUMP_METHOD void dump() const;
-#endif
-};
-
-void calculateDbgValueHistory(const MachineFunction *MF,
- const TargetRegisterInfo *TRI,
- DbgValueHistoryMap &Result);
-
-} // end namespace llvm
-
-#endif // LLVM_LIB_CODEGEN_ASMPRINTER_DBGVALUEHISTORYCALCULATOR_H
diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp b/contrib/llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp
index 82e14dc13cb1..551cd36d1984 100644
--- a/contrib/llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp
+++ b/contrib/llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.cpp
@@ -12,7 +12,7 @@
//
//===----------------------------------------------------------------------===//
-#include "DebugHandlerBase.h"
+#include "llvm/CodeGen/DebugHandlerBase.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/Twine.h"
#include "llvm/CodeGen/AsmPrinter.h"
@@ -125,6 +125,21 @@ MCSymbol *DebugHandlerBase::getLabelAfterInsn(const MachineInstr *MI) {
return LabelsAfterInsn.lookup(MI);
}
+// Return the function-local offset of an instruction.
+const MCExpr *
+DebugHandlerBase::getFunctionLocalOffsetAfterInsn(const MachineInstr *MI) {
+ MCContext &MC = Asm->OutContext;
+
+ MCSymbol *Start = Asm->getFunctionBegin();
+ const auto *StartRef = MCSymbolRefExpr::create(Start, MC);
+
+ MCSymbol *AfterInsn = getLabelAfterInsn(MI);
+ assert(AfterInsn && "Expected label after instruction");
+ const auto *AfterRef = MCSymbolRefExpr::create(AfterInsn, MC);
+
+ return MCBinaryExpr::createSub(AfterRef, StartRef, MC);
+}
+
/// 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();
@@ -190,8 +205,9 @@ void DebugHandlerBase::beginFunction(const MachineFunction *MF) {
// Calculate history for local variables.
assert(DbgValues.empty() && "DbgValues map wasn't cleaned!");
- calculateDbgValueHistory(MF, Asm->MF->getSubtarget().getRegisterInfo(),
- DbgValues);
+ assert(DbgLabels.empty() && "DbgLabels map wasn't cleaned!");
+ calculateDbgEntityHistory(MF, Asm->MF->getSubtarget().getRegisterInfo(),
+ DbgValues, DbgLabels);
LLVM_DEBUG(DbgValues.dump());
// Request labels for the full history.
@@ -229,6 +245,12 @@ void DebugHandlerBase::beginFunction(const MachineFunction *MF) {
}
}
+ // Ensure there is a symbol before DBG_LABEL.
+ for (const auto &I : DbgLabels) {
+ const MachineInstr *MI = I.second;
+ requestLabelBeforeInsn(MI);
+ }
+
PrevInstLoc = DebugLoc();
PrevLabel = Asm->getFunctionBegin();
beginFunctionImpl(MF);
@@ -296,6 +318,7 @@ void DebugHandlerBase::endFunction(const MachineFunction *MF) {
if (hasDebugInfo(MMI, MF))
endFunctionImpl(MF);
DbgValues.clear();
+ DbgLabels.clear();
LabelsBeforeInsn.clear();
LabelsAfterInsn.clear();
}
diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.h b/contrib/llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.h
deleted file mode 100644
index 1ccefe32be75..000000000000
--- a/contrib/llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.h
+++ /dev/null
@@ -1,131 +0,0 @@
-//===-- llvm/lib/CodeGen/AsmPrinter/DebugHandlerBase.h --------*- C++ -*--===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// Common functionality for different debug information format backends.
-// LLVM currently supports DWARF and CodeView.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_LIB_CODEGEN_ASMPRINTER_DEBUGHANDLERBASE_H
-#define LLVM_LIB_CODEGEN_ASMPRINTER_DEBUGHANDLERBASE_H
-
-#include "AsmPrinterHandler.h"
-#include "DbgValueHistoryCalculator.h"
-#include "llvm/ADT/Optional.h"
-#include "llvm/CodeGen/LexicalScopes.h"
-#include "llvm/CodeGen/MachineInstr.h"
-#include "llvm/IR/DebugInfoMetadata.h"
-
-namespace llvm {
-
-class AsmPrinter;
-class MachineInstr;
-class MachineModuleInfo;
-
-/// Represents the location at which a variable is stored.
-struct DbgVariableLocation {
- /// Base register.
- unsigned Register;
-
- /// Chain of offsetted loads necessary to load the value if it lives in
- /// memory. Every load except for the last is pointer-sized.
- SmallVector<int64_t, 1> LoadChain;
-
- /// Present if the location is part of a larger variable.
- llvm::Optional<llvm::DIExpression::FragmentInfo> FragmentInfo;
-
- /// Extract a VariableLocation from a MachineInstr.
- /// This will only work if Instruction is a debug value instruction
- /// and the associated DIExpression is in one of the supported forms.
- /// If these requirements are not met, the returned Optional will not
- /// have a value.
- static Optional<DbgVariableLocation>
- extractFromMachineInstruction(const MachineInstr &Instruction);
-};
-
-/// Base class for debug information backends. Common functionality related to
-/// tracking which variables and scopes are alive at a given PC live here.
-class DebugHandlerBase : public AsmPrinterHandler {
-protected:
- DebugHandlerBase(AsmPrinter *A);
-
- /// Target of debug info emission.
- AsmPrinter *Asm;
-
- /// Collected machine module information.
- MachineModuleInfo *MMI;
-
- /// Previous instruction's location information. This is used to
- /// determine label location to indicate scope boundaries in debug info.
- /// We track the previous instruction's source location (if not line 0),
- /// whether it was a label, and its parent BB.
- DebugLoc PrevInstLoc;
- MCSymbol *PrevLabel = nullptr;
- const MachineBasicBlock *PrevInstBB = nullptr;
-
- /// This location indicates end of function prologue and beginning of
- /// function body.
- DebugLoc PrologEndLoc;
-
- /// If nonnull, stores the current machine instruction we're processing.
- const MachineInstr *CurMI = nullptr;
-
- LexicalScopes LScopes;
-
- /// History of DBG_VALUE and clobber instructions for each user
- /// variable. Variables are listed in order of appearance.
- DbgValueHistoryMap DbgValues;
-
- /// Maps instruction with label emitted before instruction.
- /// FIXME: Make this private from DwarfDebug, we have the necessary accessors
- /// for it.
- DenseMap<const MachineInstr *, MCSymbol *> LabelsBeforeInsn;
-
- /// Maps instruction with label emitted after instruction.
- DenseMap<const MachineInstr *, MCSymbol *> LabelsAfterInsn;
-
- /// Indentify instructions that are marking the beginning of or
- /// ending of a scope.
- void identifyScopeMarkers();
-
- /// Ensure that a label will be emitted before MI.
- void requestLabelBeforeInsn(const MachineInstr *MI) {
- LabelsBeforeInsn.insert(std::make_pair(MI, nullptr));
- }
-
- /// Ensure that a label will be emitted after MI.
- void requestLabelAfterInsn(const MachineInstr *MI) {
- LabelsAfterInsn.insert(std::make_pair(MI, nullptr));
- }
-
- virtual void beginFunctionImpl(const MachineFunction *MF) = 0;
- virtual void endFunctionImpl(const MachineFunction *MF) = 0;
- virtual void skippedNonDebugFunction() {}
-
- // AsmPrinterHandler overrides.
-public:
- void beginInstruction(const MachineInstr *MI) override;
- void endInstruction() override;
-
- void beginFunction(const MachineFunction *MF) override;
- void endFunction(const MachineFunction *MF) override;
-
- /// Return Label preceding the instruction.
- MCSymbol *getLabelBeforeInsn(const MachineInstr *MI);
-
- /// Return Label immediately following the instruction.
- MCSymbol *getLabelAfterInsn(const MachineInstr *MI);
-
- /// If this type is derived from a base type then return base type size.
- static uint64_t getBaseTypeSize(const DITypeRef TyRef);
-};
-
-}
-
-#endif
diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/DebugLocEntry.h b/contrib/llvm/lib/CodeGen/AsmPrinter/DebugLocEntry.h
index ac49657b68fa..befa4b941c8d 100644
--- a/contrib/llvm/lib/CodeGen/AsmPrinter/DebugLocEntry.h
+++ b/contrib/llvm/lib/CodeGen/AsmPrinter/DebugLocEntry.h
@@ -139,7 +139,7 @@ public:
// Sort the pieces by offset.
// Remove any duplicate entries by dropping all but the first.
void sortUniqueValues() {
- llvm::sort(Values.begin(), Values.end());
+ llvm::sort(Values);
Values.erase(
std::unique(
Values.begin(), Values.end(), [](const Value &A, const Value &B) {
diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
index 32271a0ef24a..1dca3f0fce5b 100644
--- a/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
+++ b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
@@ -69,14 +69,16 @@ void DwarfCompileUnit::addLabelAddress(DIE &Die, dwarf::Attribute Attribute,
// pool from the skeleton - maybe even in non-fission (possibly fewer
// relocations by sharing them in the pool, but we have other ideas about how
// to reduce the number of relocations as well/instead).
- if (!DD->useSplitDwarf() || !Skeleton)
+ if ((!DD->useSplitDwarf() || !Skeleton) && DD->getDwarfVersion() < 5)
return addLocalLabelAddress(Die, Attribute, Label);
if (Label)
DD->addArangeLabel(SymbolCU(this, Label));
unsigned idx = DD->getAddressPool().getIndex(Label);
- Die.addValue(DIEValueAllocator, Attribute, dwarf::DW_FORM_GNU_addr_index,
+ Die.addValue(DIEValueAllocator, Attribute,
+ DD->getDwarfVersion() >= 5 ? dwarf::DW_FORM_addrx
+ : dwarf::DW_FORM_GNU_addr_index,
DIEInteger(idx));
}
@@ -160,6 +162,9 @@ DIE *DwarfCompileUnit::getOrCreateGlobalVariableDIE(
addUInt(*VariableDIE, dwarf::DW_AT_alignment, dwarf::DW_FORM_udata,
AlignInBytes);
+ if (MDTuple *TP = GV->getTemplateParams())
+ addTemplateParams(*VariableDIE, DINodeArray(TP));
+
// Add location.
bool addToAccelTable = false;
DIELoc *Loc = nullptr;
@@ -186,6 +191,10 @@ DIE *DwarfCompileUnit::getOrCreateGlobalVariableDIE(
if (!Global && (!Expr || !Expr->isConstant()))
continue;
+ if (Global && Global->isThreadLocal() &&
+ !Asm->getObjFileLowering().supportDebugThreadLocalLocation())
+ continue;
+
if (!Loc) {
addToAccelTable = true;
Loc = new (DIEValueAllocator) DIELoc;
@@ -245,13 +254,13 @@ DIE *DwarfCompileUnit::getOrCreateGlobalVariableDIE(
addLinkageName(*VariableDIE, GV->getLinkageName());
if (addToAccelTable) {
- DD->addAccelName(GV->getName(), *VariableDIE);
+ DD->addAccelName(*CUNode, GV->getName(), *VariableDIE);
// If the linkage name is different than the name, go ahead and output
// that as well into the name table.
if (GV->getLinkageName() != "" && GV->getName() != GV->getLinkageName() &&
DD->useAllLinkageNames())
- DD->addAccelName(GV->getLinkageName(), *VariableDIE);
+ DD->addAccelName(*CUNode, GV->getLinkageName(), *VariableDIE);
}
return VariableDIE;
@@ -268,6 +277,7 @@ void DwarfCompileUnit::addRange(RangeSpan Range) {
(&CURanges.back().getEnd()->getSection() !=
&Range.getEnd()->getSection())) {
CURanges.push_back(Range);
+ DD->addSectionLabel(Range.getStart());
return;
}
@@ -275,6 +285,9 @@ void DwarfCompileUnit::addRange(RangeSpan Range) {
}
void DwarfCompileUnit::initStmtList() {
+ if (CUNode->isDebugDirectivesOnly())
+ return;
+
// Define start line table label for each Compile Unit.
MCSymbol *LineTableStartSym;
const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering();
@@ -341,7 +354,7 @@ DIE &DwarfCompileUnit::updateSubprogramScopeDIE(const DISubprogram *SP) {
// Add name to the name table, we do this here because we're guaranteed
// to have concrete versions of our DW_TAG_subprogram nodes.
- DD->addSubprogramNames(SP, *SPDie);
+ DD->addSubprogramNames(*CUNode, SP, *SPDie);
return *SPDie;
}
@@ -412,24 +425,29 @@ void DwarfCompileUnit::addScopeRangeList(DIE &ScopeDIE,
? TLOF.getDwarfRnglistsSection()->getBeginSymbol()
: TLOF.getDwarfRangesSection()->getBeginSymbol();
- RangeSpanList List(Asm->createTempSymbol("debug_ranges"), std::move(Range));
+ HasRangeLists = true;
+
+ // Add the range list to the set of ranges to be emitted.
+ auto IndexAndList =
+ (DD->getDwarfVersion() < 5 && Skeleton ? Skeleton->DU : DU)
+ ->addRange(*(Skeleton ? Skeleton : this), std::move(Range));
+
+ uint32_t Index = IndexAndList.first;
+ auto &List = *IndexAndList.second;
// Under fission, ranges are specified by constant offsets relative to the
// CU's DW_AT_GNU_ranges_base.
// FIXME: For DWARF v5, do not generate the DW_AT_ranges attribute under
// fission until we support the forms using the .debug_addr section
// (DW_RLE_startx_endx etc.).
- if (isDwoUnit()) {
- if (DD->getDwarfVersion() < 5)
- addSectionDelta(ScopeDIE, dwarf::DW_AT_ranges, List.getSym(),
- RangeSectionSym);
- } else {
+ if (DD->getDwarfVersion() >= 5)
+ addUInt(ScopeDIE, dwarf::DW_AT_ranges, dwarf::DW_FORM_rnglistx, Index);
+ else if (isDwoUnit())
+ addSectionDelta(ScopeDIE, dwarf::DW_AT_ranges, List.getSym(),
+ RangeSectionSym);
+ else
addSectionLabel(ScopeDIE, dwarf::DW_AT_ranges, List.getSym(),
RangeSectionSym);
- }
-
- // Add the range list to the set of ranges to be emitted.
- (Skeleton ? Skeleton : this)->CURangeLists.push_back(std::move(List));
}
void DwarfCompileUnit::attachRangesOrLowHighPC(
@@ -479,7 +497,7 @@ DIE *DwarfCompileUnit::constructInlinedScopeDIE(LexicalScope *Scope) {
// Add name to the name table, we do this here because we're guaranteed
// to have concrete versions of our DW_TAG_inlined_subprogram nodes.
- DD->addSubprogramNames(InlinedSP, *ScopeDIE);
+ DD->addSubprogramNames(*CUNode, InlinedSP, *ScopeDIE);
return ScopeDIE;
}
@@ -506,6 +524,18 @@ DIE *DwarfCompileUnit::constructVariableDIE(DbgVariable &DV, bool Abstract) {
return D;
}
+DIE *DwarfCompileUnit::constructLabelDIE(DbgLabel &DL,
+ const LexicalScope &Scope) {
+ auto LabelDie = DIE::get(DIEValueAllocator, DL.getTag());
+ insertDIE(DL.getLabel(), LabelDie);
+ DL.setDIE(*LabelDie);
+
+ if (Scope.isAbstractScope())
+ applyLabelAttributes(DL, *LabelDie);
+
+ return LabelDie;
+}
+
DIE *DwarfCompileUnit::constructVariableDIEImpl(const DbgVariable &DV,
bool Abstract) {
// Define variable debug information entry.
@@ -699,13 +729,17 @@ DIE *DwarfCompileUnit::createScopeChildrenDIE(LexicalScope *Scope,
if (HasNonScopeChildren)
*HasNonScopeChildren = !Children.empty();
+ for (DbgLabel *DL : DU->getScopeLabels().lookup(Scope))
+ Children.push_back(constructLabelDIE(*DL, *Scope));
+
for (LexicalScope *LS : Scope->getChildren())
constructScopeDIE(LS, Children);
return ObjectPointer;
}
-void DwarfCompileUnit::constructSubprogramScopeDIE(const DISubprogram *Sub, LexicalScope *Scope) {
+DIE &DwarfCompileUnit::constructSubprogramScopeDIE(const DISubprogram *Sub,
+ LexicalScope *Scope) {
DIE &ScopeDIE = updateSubprogramScopeDIE(Sub);
if (Scope) {
@@ -728,6 +762,8 @@ void DwarfCompileUnit::constructSubprogramScopeDIE(const DISubprogram *Sub, Lexi
!includeMinimalInlineScopes())
ScopeDIE.addChild(
DIE::get(DIEValueAllocator, dwarf::DW_TAG_unspecified_parameters));
+
+ return ScopeDIE;
}
DIE *DwarfCompileUnit::createAndAddScopeChildren(LexicalScope *Scope,
@@ -782,6 +818,32 @@ void DwarfCompileUnit::constructAbstractSubprogramScopeDIE(
ContextCU->addDIEEntry(*AbsDef, dwarf::DW_AT_object_pointer, *ObjectPointer);
}
+DIE &DwarfCompileUnit::constructCallSiteEntryDIE(DIE &ScopeDIE,
+ const DISubprogram &CalleeSP,
+ bool IsTail,
+ const MCExpr *PCOffset) {
+ // Insert a call site entry DIE within ScopeDIE.
+ DIE &CallSiteDIE =
+ createAndAddDIE(dwarf::DW_TAG_call_site, ScopeDIE, nullptr);
+
+ // For the purposes of showing tail call frames in backtraces, a key piece of
+ // information is DW_AT_call_origin, a pointer to the callee DIE.
+ DIE *CalleeDIE = getOrCreateSubprogramDIE(&CalleeSP);
+ assert(CalleeDIE && "Could not create DIE for call site entry origin");
+ addDIEEntry(CallSiteDIE, dwarf::DW_AT_call_origin, *CalleeDIE);
+
+ if (IsTail) {
+ // Attach DW_AT_call_tail_call to tail calls for standards compliance.
+ addFlag(CallSiteDIE, dwarf::DW_AT_call_tail_call);
+ } else {
+ // Attach the return PC to allow the debugger to disambiguate call paths
+ // from one function to another.
+ assert(PCOffset && "Missing return PC information for a call");
+ addAddressExpr(CallSiteDIE, dwarf::DW_AT_call_return_pc, PCOffset);
+ }
+ return CallSiteDIE;
+}
+
DIE *DwarfCompileUnit::constructImportedEntityDIE(
const DIImportedEntity *Module) {
DIE *IMDie = DIE::get(DIEValueAllocator, (dwarf::Tag)Module->getTag());
@@ -824,40 +886,51 @@ void DwarfCompileUnit::finishSubprogramDefinition(const DISubprogram *SP) {
}
}
-void DwarfCompileUnit::finishVariableDefinition(const DbgVariable &Var) {
- DbgVariable *AbsVar = getExistingAbstractVariable(
- InlinedVariable(Var.getVariable(), Var.getInlinedAt()));
- auto *VariableDie = Var.getDIE();
- if (AbsVar && AbsVar->getDIE()) {
- addDIEEntry(*VariableDie, dwarf::DW_AT_abstract_origin,
- *AbsVar->getDIE());
- } else
- applyVariableAttributes(Var, *VariableDie);
-}
+void DwarfCompileUnit::finishEntityDefinition(const DbgEntity *Entity) {
+ DbgEntity *AbsEntity = getExistingAbstractEntity(Entity->getEntity());
-DbgVariable *DwarfCompileUnit::getExistingAbstractVariable(InlinedVariable IV) {
- const DILocalVariable *Cleansed;
- return getExistingAbstractVariable(IV, Cleansed);
+ auto *Die = Entity->getDIE();
+ /// Label may be used to generate DW_AT_low_pc, so put it outside
+ /// if/else block.
+ const DbgLabel *Label = nullptr;
+ if (AbsEntity && AbsEntity->getDIE()) {
+ addDIEEntry(*Die, dwarf::DW_AT_abstract_origin, *AbsEntity->getDIE());
+ Label = dyn_cast<const DbgLabel>(Entity);
+ } else {
+ if (const DbgVariable *Var = dyn_cast<const DbgVariable>(Entity))
+ applyVariableAttributes(*Var, *Die);
+ else if ((Label = dyn_cast<const DbgLabel>(Entity)))
+ applyLabelAttributes(*Label, *Die);
+ else
+ llvm_unreachable("DbgEntity must be DbgVariable or DbgLabel.");
+ }
+
+ if (Label)
+ if (const auto *Sym = Label->getSymbol())
+ addLabelAddress(*Die, dwarf::DW_AT_low_pc, Sym);
}
-// Find abstract variable, if any, associated with Var.
-DbgVariable *DwarfCompileUnit::getExistingAbstractVariable(
- InlinedVariable IV, const DILocalVariable *&Cleansed) {
- // More then one inlined variable corresponds to one abstract variable.
- Cleansed = IV.first;
- auto &AbstractVariables = getAbstractVariables();
- auto I = AbstractVariables.find(Cleansed);
- if (I != AbstractVariables.end())
+DbgEntity *DwarfCompileUnit::getExistingAbstractEntity(const DINode *Node) {
+ auto &AbstractEntities = getAbstractEntities();
+ auto I = AbstractEntities.find(Node);
+ if (I != AbstractEntities.end())
return I->second.get();
return nullptr;
}
-void DwarfCompileUnit::createAbstractVariable(const DILocalVariable *Var,
- LexicalScope *Scope) {
+void DwarfCompileUnit::createAbstractEntity(const DINode *Node,
+ LexicalScope *Scope) {
assert(Scope && Scope->isAbstractScope());
- auto AbsDbgVariable = llvm::make_unique<DbgVariable>(Var, /* IA */ nullptr);
- DU->addScopeVariable(Scope, AbsDbgVariable.get());
- getAbstractVariables()[Var] = std::move(AbsDbgVariable);
+ auto &Entity = getAbstractEntities()[Node];
+ if (isa<const DILocalVariable>(Node)) {
+ Entity = llvm::make_unique<DbgVariable>(
+ cast<const DILocalVariable>(Node), nullptr /* IA */);;
+ DU->addScopeVariable(Scope, cast<DbgVariable>(Entity.get()));
+ } else if (isa<const DILabel>(Node)) {
+ Entity = llvm::make_unique<DbgLabel>(
+ cast<const DILabel>(Node), nullptr /* IA */);
+ DU->addScopeLabel(Scope, cast<DbgLabel>(Entity.get()));
+ }
}
void DwarfCompileUnit::emitHeader(bool UseOffsets) {
@@ -876,13 +949,18 @@ void DwarfCompileUnit::emitHeader(bool UseOffsets) {
}
bool DwarfCompileUnit::hasDwarfPubSections() const {
- // Opting in to GNU Pubnames/types overrides the default to ensure these are
- // generated for things like Gold's gdb_index generation.
- if (CUNode->getGnuPubnames())
+ switch (CUNode->getNameTableKind()) {
+ case DICompileUnit::DebugNameTableKind::None:
+ return false;
+ // Opting in to GNU Pubnames/types overrides the default to ensure these are
+ // generated for things like Gold's gdb_index generation.
+ case DICompileUnit::DebugNameTableKind::GNU:
return true;
-
- return DD->tuneForGDB() && DD->usePubSections() &&
- !includeMinimalInlineScopes();
+ case DICompileUnit::DebugNameTableKind::Default:
+ return DD->tuneForGDB() && !includeMinimalInlineScopes() &&
+ !CUNode->isDebugDirectivesOnly();
+ }
+ llvm_unreachable("Unhandled DICompileUnit::DebugNameTableKind enum");
}
/// addGlobalName - Add a new global name to the compile unit.
@@ -939,8 +1017,6 @@ void DwarfCompileUnit::addVariableAddress(const DbgVariable &DV, DIE &Die,
"block byref variable without a complex expression");
if (DV.hasComplexAddress())
addComplexAddress(DV, Die, dwarf::DW_AT_location, Location);
- else if (DV.isBlockByrefVariable())
- addBlockByrefAddress(DV, Die, dwarf::DW_AT_location, Location);
else
addAddress(Die, dwarf::DW_AT_location, Location);
}
@@ -1012,12 +1088,27 @@ void DwarfCompileUnit::applyVariableAttributes(const DbgVariable &Var,
addFlag(VariableDie, dwarf::DW_AT_artificial);
}
+void DwarfCompileUnit::applyLabelAttributes(const DbgLabel &Label,
+ DIE &LabelDie) {
+ StringRef Name = Label.getName();
+ if (!Name.empty())
+ addString(LabelDie, dwarf::DW_AT_name, Name);
+ const auto *DILabel = Label.getLabel();
+ addSourceLine(LabelDie, DILabel);
+}
+
/// Add a Dwarf expression attribute data and value.
void DwarfCompileUnit::addExpr(DIELoc &Die, dwarf::Form Form,
const MCExpr *Expr) {
Die.addValue(DIEValueAllocator, (dwarf::Attribute)0, Form, DIEExpr(Expr));
}
+void DwarfCompileUnit::addAddressExpr(DIE &Die, dwarf::Attribute Attribute,
+ const MCExpr *Expr) {
+ Die.addValue(DIEValueAllocator, Attribute, dwarf::DW_FORM_addr,
+ DIEExpr(Expr));
+}
+
void DwarfCompileUnit::applySubprogramAttributesToDefinition(
const DISubprogram *SP, DIE &SPDie) {
auto *SPDecl = SP->getDeclaration();
@@ -1034,3 +1125,12 @@ bool DwarfCompileUnit::includeMinimalInlineScopes() const {
return getCUNode()->getEmissionKind() == DICompileUnit::LineTablesOnly ||
(DD->useSplitDwarf() && !Skeleton);
}
+
+void DwarfCompileUnit::addAddrTableBase() {
+ const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering();
+ MCSymbol *Label = DD->getAddressPool().getLabel();
+ addSectionLabel(getUnitDie(),
+ getDwarfVersion() >= 5 ? dwarf::DW_AT_addr_base
+ : dwarf::DW_AT_GNU_addr_base,
+ Label, TLOF.getDwarfAddrSection()->getBeginSymbol());
+}
diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h
index 51e1558fe4a3..9ec22f68c12f 100644
--- a/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h
+++ b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h
@@ -14,7 +14,6 @@
#ifndef LLVM_LIB_CODEGEN_ASMPRINTER_DWARFCOMPILEUNIT_H
#define LLVM_LIB_CODEGEN_ASMPRINTER_DWARFCOMPILEUNIT_H
-#include "DbgValueHistoryCalculator.h"
#include "DwarfDebug.h"
#include "DwarfUnit.h"
#include "llvm/ADT/ArrayRef.h"
@@ -23,6 +22,7 @@
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/BinaryFormat/Dwarf.h"
+#include "llvm/CodeGen/DbgEntityHistoryCalculator.h"
#include "llvm/CodeGen/DIE.h"
#include "llvm/CodeGen/LexicalScopes.h"
#include "llvm/IR/DebugInfoMetadata.h"
@@ -44,6 +44,7 @@ class MDNode;
class DwarfCompileUnit final : public DwarfUnit {
/// A numeric ID unique among all CUs in the module
unsigned UniqueID;
+ bool HasRangeLists = false;
/// The attribute index of DW_AT_stmt_list in the compile unit DIE, avoiding
/// the need to search for it in applyStmtList.
@@ -69,10 +70,6 @@ class DwarfCompileUnit final : public DwarfUnit {
/// GlobalTypes - A map of globally visible types for this unit.
StringMap<const DIE *> GlobalTypes;
- // List of range lists for a given compile unit, separate from the ranges for
- // the CU itself.
- SmallVector<RangeSpanList, 1> CURangeLists;
-
// List of ranges for a given compile unit.
SmallVector<RangeSpan, 2> CURanges;
@@ -81,7 +78,7 @@ class DwarfCompileUnit final : public DwarfUnit {
const MCSymbol *BaseAddress = nullptr;
DenseMap<const MDNode *, DIE *> AbstractSPDies;
- DenseMap<const MDNode *, std::unique_ptr<DbgVariable>> AbstractVariables;
+ DenseMap<const DINode *, std::unique_ptr<DbgEntity>> AbstractEntities;
/// DWO ID for correlating skeleton and split units.
uint64_t DWOId = 0;
@@ -98,16 +95,17 @@ class DwarfCompileUnit final : public DwarfUnit {
return DU->getAbstractSPDies();
}
- DenseMap<const MDNode *, std::unique_ptr<DbgVariable>> &getAbstractVariables() {
+ DenseMap<const DINode *, std::unique_ptr<DbgEntity>> &getAbstractEntities() {
if (isDwoUnit() && !DD->shareAcrossDWOCUs())
- return AbstractVariables;
- return DU->getAbstractVariables();
+ return AbstractEntities;
+ return DU->getAbstractEntities();
}
public:
DwarfCompileUnit(unsigned UID, const DICompileUnit *Node, AsmPrinter *A,
DwarfDebug *DW, DwarfFile *DWU);
+ bool hasRangeLists() const { return HasRangeLists; }
unsigned getUniqueID() const { return UniqueID; }
DwarfCompileUnit *getSkeleton() const {
@@ -194,30 +192,39 @@ public:
DIE *constructVariableDIE(DbgVariable &DV, const LexicalScope &Scope,
DIE *&ObjectPointer);
+ /// Construct a DIE for the given DbgLabel.
+ DIE *constructLabelDIE(DbgLabel &DL, const LexicalScope &Scope);
+
/// A helper function to create children of a Scope DIE.
DIE *createScopeChildrenDIE(LexicalScope *Scope,
SmallVectorImpl<DIE *> &Children,
bool *HasNonScopeChildren = nullptr);
/// Construct a DIE for this subprogram scope.
- void constructSubprogramScopeDIE(const DISubprogram *Sub, LexicalScope *Scope);
+ DIE &constructSubprogramScopeDIE(const DISubprogram *Sub,
+ LexicalScope *Scope);
DIE *createAndAddScopeChildren(LexicalScope *Scope, DIE &ScopeDIE);
void constructAbstractSubprogramScopeDIE(LexicalScope *Scope);
+ /// Construct a call site entry DIE describing a call within \p Scope to a
+ /// callee described by \p CalleeSP. \p IsTail specifies whether the call is
+ /// a tail call. \p PCOffset must be non-zero for non-tail calls or be the
+ /// function-local offset to PC value after the call instruction.
+ DIE &constructCallSiteEntryDIE(DIE &ScopeDIE, const DISubprogram &CalleeSP,
+ bool IsTail, const MCExpr *PCOffset);
+
/// Construct import_module DIE.
DIE *constructImportedEntityDIE(const DIImportedEntity *Module);
void finishSubprogramDefinition(const DISubprogram *SP);
- void finishVariableDefinition(const DbgVariable &Var);
+ void finishEntityDefinition(const DbgEntity *Entity);
/// Find abstract variable associated with Var.
- using InlinedVariable = DbgValueHistoryMap::InlinedVariable;
- DbgVariable *getExistingAbstractVariable(InlinedVariable IV,
- const DILocalVariable *&Cleansed);
- DbgVariable *getExistingAbstractVariable(InlinedVariable IV);
- void createAbstractVariable(const DILocalVariable *Var, LexicalScope *Scope);
+ using InlinedEntity = DbgValueHistoryMap::InlinedEntity;
+ DbgEntity *getExistingAbstractEntity(const DINode *Node);
+ void createAbstractEntity(const DINode *Node, LexicalScope *Scope);
/// Set the skeleton unit associated with this unit.
void setSkeleton(DwarfCompileUnit &Skel) { Skeleton = &Skel; }
@@ -236,6 +243,9 @@ public:
void emitHeader(bool UseOffsets) override;
+ /// Add the DW_AT_addr_base attribute to the unit DIE.
+ void addAddrTableBase();
+
MCSymbol *getLabelBegin() const {
assert(getSection());
return LabelBegin;
@@ -285,13 +295,13 @@ public:
/// Add a Dwarf expression attribute data and value.
void addExpr(DIELoc &Die, dwarf::Form Form, const MCExpr *Expr);
+ /// Add an attribute containing an address expression to \p Die.
+ void addAddressExpr(DIE &Die, dwarf::Attribute Attribute, const MCExpr *Expr);
+
void applySubprogramAttributesToDefinition(const DISubprogram *SP,
DIE &SPDie);
- /// getRangeLists - Get the vector of range lists.
- const SmallVectorImpl<RangeSpanList> &getRangeLists() const {
- return (Skeleton ? Skeleton : this)->CURangeLists;
- }
+ void applyLabelAttributes(const DbgLabel &Label, DIE &LabelDie);
/// getRanges - Get the list of ranges for this unit.
const SmallVectorImpl<RangeSpan> &getRanges() const { return CURanges; }
diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
index 19b3afef34b5..1de2ffb6cfa1 100644
--- a/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
+++ b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
@@ -39,6 +39,7 @@
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/CodeGen/MachineOperand.h"
+#include "llvm/CodeGen/TargetInstrInfo.h"
#include "llvm/CodeGen/TargetRegisterInfo.h"
#include "llvm/CodeGen/TargetSubtargetInfo.h"
#include "llvm/IR/Constants.h"
@@ -130,11 +131,6 @@ DwarfInlinedStrings("dwarf-inlined-strings", cl::Hidden,
cl::init(Default));
static cl::opt<bool>
- NoDwarfPubSections("no-dwarf-pub-sections", cl::Hidden,
- cl::desc("Disable emission of DWARF pub sections."),
- cl::init(false));
-
-static cl::opt<bool>
NoDwarfRangesSection("no-dwarf-ranges-section", cl::Hidden,
cl::desc("Disable emission .debug_ranges section."),
cl::init(false));
@@ -188,12 +184,12 @@ bool DebugLocDwarfExpression::isFrameRegister(const TargetRegisterInfo &TRI,
}
bool DbgVariable::isBlockByrefVariable() const {
- assert(Var && "Invalid complex DbgVariable!");
- return Var->getType().resolve()->isBlockByrefStruct();
+ assert(getVariable() && "Invalid complex DbgVariable!");
+ return getVariable()->getType().resolve()->isBlockByrefStruct();
}
const DIType *DbgVariable::getType() const {
- DIType *Ty = Var->getType().resolve();
+ DIType *Ty = getVariable()->getType().resolve();
// FIXME: isBlockByrefVariable should be reformulated in terms of complex
// addresses instead.
if (Ty->isBlockByrefStruct()) {
@@ -246,7 +242,7 @@ ArrayRef<DbgVariable::FrameIndexExpr> DbgVariable::getFrameIndexExprs() const {
return A.Expr->isFragment();
}) &&
"multiple FI expressions without DW_OP_LLVM_fragment");
- llvm::sort(FrameIndexExprs.begin(), FrameIndexExprs.end(),
+ llvm::sort(FrameIndexExprs,
[](const FrameIndexExpr &A, const FrameIndexExpr &B) -> bool {
return A.Expr->getFragmentInfo()->OffsetInBits <
B.Expr->getFragmentInfo()->OffsetInBits;
@@ -258,8 +254,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(V.Var == Var && "conflicting variable");
- assert(V.IA == IA && "conflicting inlined-at location");
+ assert(V.getVariable() == getVariable() && "conflicting variable");
+ assert(V.getInlinedAt() == getInlinedAt() && "conflicting inlined-at location");
assert(!FrameIndexExprs.empty() && "Expected an MMI entry");
assert(!V.FrameIndexExprs.empty() && "Expected an MMI entry");
@@ -355,7 +351,6 @@ DwarfDebug::DwarfDebug(AsmPrinter *A, Module *M)
DwarfVersion =
TT.isNVPTX() ? 2 : (DwarfVersion ? DwarfVersion : dwarf::DWARF_VERSION);
- UsePubSections = !NoDwarfPubSections && !TT.isNVPTX();
UseRangesSection = !NoDwarfRangesSection && !TT.isNVPTX();
// Use sections as references. Force for NVPTX.
@@ -421,30 +416,35 @@ static StringRef getObjCMethodName(StringRef In) {
}
// Add the various names to the Dwarf accelerator table names.
-void DwarfDebug::addSubprogramNames(const DISubprogram *SP, DIE &Die) {
+void DwarfDebug::addSubprogramNames(const DICompileUnit &CU,
+ const DISubprogram *SP, DIE &Die) {
+ if (getAccelTableKind() != AccelTableKind::Apple &&
+ CU.getNameTableKind() == DICompileUnit::DebugNameTableKind::None)
+ return;
+
if (!SP->isDefinition())
return;
if (SP->getName() != "")
- addAccelName(SP->getName(), Die);
+ addAccelName(CU, SP->getName(), Die);
// If the linkage name is different than the name, go ahead and output that as
// well into the name table. Only do that if we are going to actually emit
// that name.
if (SP->getLinkageName() != "" && SP->getName() != SP->getLinkageName() &&
(useAllLinkageNames() || InfoHolder.getAbstractSPDies().lookup(SP)))
- addAccelName(SP->getLinkageName(), Die);
+ addAccelName(CU, SP->getLinkageName(), Die);
// If this is an Objective-C selector name add it to the ObjC accelerator
// too.
if (isObjCClass(SP->getName())) {
StringRef Class, Category;
getObjCClassCategory(SP->getName(), Class, Category);
- addAccelObjC(Class, Die);
+ addAccelObjC(CU, Class, Die);
if (Category != "")
- addAccelObjC(Category, Die);
+ addAccelObjC(CU, Category, Die);
// Also add the base method name to the name table.
- addAccelName(getObjCMethodName(SP->getName()), Die);
+ addAccelName(CU, getObjCMethodName(SP->getName()), Die);
}
}
@@ -503,6 +503,64 @@ void DwarfDebug::constructAbstractSubprogramScopeDIE(DwarfCompileUnit &SrcCU,
}
}
+void DwarfDebug::constructCallSiteEntryDIEs(const DISubprogram &SP,
+ DwarfCompileUnit &CU, DIE &ScopeDIE,
+ const MachineFunction &MF) {
+ // Add a call site-related attribute (DWARF5, Sec. 3.3.1.3). Do this only if
+ // the subprogram is required to have one.
+ if (!SP.areAllCallsDescribed() || !SP.isDefinition())
+ return;
+
+ // Use DW_AT_call_all_calls to express that call site entries are present
+ // for both tail and non-tail calls. Don't use DW_AT_call_all_source_calls
+ // because one of its requirements is not met: call site entries for
+ // optimized-out calls are elided.
+ CU.addFlag(ScopeDIE, dwarf::DW_AT_call_all_calls);
+
+ const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo();
+ assert(TII && "TargetInstrInfo not found: cannot label tail calls");
+
+ // Emit call site entries for each call or tail call in the function.
+ for (const MachineBasicBlock &MBB : MF) {
+ for (const MachineInstr &MI : MBB.instrs()) {
+ // Skip instructions which aren't calls. Both calls and tail-calling jump
+ // instructions (e.g TAILJMPd64) are classified correctly here.
+ if (!MI.isCall())
+ continue;
+
+ // TODO: Add support for targets with delay slots (see: beginInstruction).
+ if (MI.hasDelaySlot())
+ return;
+
+ // If this is a direct call, find the callee's subprogram.
+ const MachineOperand &CalleeOp = MI.getOperand(0);
+ if (!CalleeOp.isGlobal())
+ continue;
+ const Function *CalleeDecl = dyn_cast<Function>(CalleeOp.getGlobal());
+ if (!CalleeDecl || !CalleeDecl->getSubprogram())
+ continue;
+
+ // TODO: Omit call site entries for runtime calls (objc_msgSend, etc).
+ // TODO: Add support for indirect calls.
+
+ bool IsTail = TII->isTailCall(MI);
+
+ // For tail calls, no return PC information is needed. For regular calls,
+ // the return PC is needed to disambiguate paths in the call graph which
+ // could lead to some target function.
+ const MCExpr *PCOffset =
+ IsTail ? nullptr : getFunctionLocalOffsetAfterInsn(&MI);
+
+ assert((IsTail || PCOffset) && "Call without return PC information");
+ LLVM_DEBUG(dbgs() << "CallSiteEntry: " << MF.getName() << " -> "
+ << CalleeDecl->getName() << (IsTail ? " [tail]" : "")
+ << "\n");
+ CU.constructCallSiteEntryDIE(ScopeDIE, *CalleeDecl->getSubprogram(),
+ IsTail, PCOffset);
+ }
+ }
+}
+
void DwarfDebug::addGnuPubAttributes(DwarfCompileUnit &U, DIE &D) const {
if (!U.hasDwarfPubSections())
return;
@@ -510,41 +568,14 @@ void DwarfDebug::addGnuPubAttributes(DwarfCompileUnit &U, DIE &D) const {
U.addFlag(D, dwarf::DW_AT_GNU_pubnames);
}
-// Create new DwarfCompileUnit for the given metadata node with tag
-// DW_TAG_compile_unit.
-DwarfCompileUnit &
-DwarfDebug::getOrCreateDwarfCompileUnit(const DICompileUnit *DIUnit) {
- if (auto *CU = CUMap.lookup(DIUnit))
- return *CU;
- StringRef FN = DIUnit->getFilename();
- CompilationDir = DIUnit->getDirectory();
-
- auto OwnedUnit = llvm::make_unique<DwarfCompileUnit>(
- InfoHolder.getUnits().size(), DIUnit, Asm, this, &InfoHolder);
- DwarfCompileUnit &NewCU = *OwnedUnit;
+void DwarfDebug::finishUnitAttributes(const DICompileUnit *DIUnit,
+ DwarfCompileUnit &NewCU) {
DIE &Die = NewCU.getUnitDie();
- InfoHolder.addUnit(std::move(OwnedUnit));
- if (useSplitDwarf()) {
- NewCU.setSkeleton(constructSkeletonCU(NewCU));
- NewCU.addString(Die, dwarf::DW_AT_GNU_dwo_name,
- Asm->TM.Options.MCOptions.SplitDwarfFile);
- }
-
- for (auto *IE : DIUnit->getImportedEntities())
- NewCU.addImportedEntity(IE);
-
- // LTO with assembly output shares a single line table amongst multiple CUs.
- // To avoid the compilation directory being ambiguous, let the line table
- // explicitly describe the directory of all files, never relying on the
- // compilation directory.
- if (!Asm->OutStreamer->hasRawTextSupport() || SingleCU)
- Asm->OutStreamer->emitDwarfFile0Directive(
- CompilationDir, FN, NewCU.getMD5AsBytes(DIUnit->getFile()),
- DIUnit->getSource(), NewCU.getUniqueID());
+ StringRef FN = DIUnit->getFilename();
StringRef Producer = DIUnit->getProducer();
StringRef Flags = DIUnit->getFlags();
- if (!Flags.empty()) {
+ if (!Flags.empty() && !useAppleExtensionAttributes()) {
std::string ProducerWithFlags = Producer.str() + " " + Flags.str();
NewCU.addString(Die, dwarf::DW_AT_producer, ProducerWithFlags);
} else
@@ -582,11 +613,6 @@ DwarfDebug::getOrCreateDwarfCompileUnit(const DICompileUnit *DIUnit) {
dwarf::DW_FORM_data1, RVer);
}
- if (useSplitDwarf())
- NewCU.setSection(Asm->getObjFileLowering().getDwarfInfoDWOSection());
- else
- NewCU.setSection(Asm->getObjFileLowering().getDwarfInfoSection());
-
if (DIUnit->getDWOId()) {
// This CU is either a clang module DWO or a skeleton CU.
NewCU.addUInt(Die, dwarf::DW_AT_GNU_dwo_id, dwarf::DW_FORM_data8,
@@ -596,9 +622,44 @@ DwarfDebug::getOrCreateDwarfCompileUnit(const DICompileUnit *DIUnit) {
NewCU.addString(Die, dwarf::DW_AT_GNU_dwo_name,
DIUnit->getSplitDebugFilename());
}
+}
+// Create new DwarfCompileUnit for the given metadata node with tag
+// DW_TAG_compile_unit.
+DwarfCompileUnit &
+DwarfDebug::getOrCreateDwarfCompileUnit(const DICompileUnit *DIUnit) {
+ if (auto *CU = CUMap.lookup(DIUnit))
+ return *CU;
+
+ CompilationDir = DIUnit->getDirectory();
+
+ auto OwnedUnit = llvm::make_unique<DwarfCompileUnit>(
+ InfoHolder.getUnits().size(), DIUnit, Asm, this, &InfoHolder);
+ DwarfCompileUnit &NewCU = *OwnedUnit;
+ InfoHolder.addUnit(std::move(OwnedUnit));
+
+ for (auto *IE : DIUnit->getImportedEntities())
+ NewCU.addImportedEntity(IE);
+
+ // LTO with assembly output shares a single line table amongst multiple CUs.
+ // To avoid the compilation directory being ambiguous, let the line table
+ // explicitly describe the directory of all files, never relying on the
+ // compilation directory.
+ if (!Asm->OutStreamer->hasRawTextSupport() || SingleCU)
+ Asm->OutStreamer->emitDwarfFile0Directive(
+ CompilationDir, DIUnit->getFilename(),
+ NewCU.getMD5AsBytes(DIUnit->getFile()), DIUnit->getSource(),
+ NewCU.getUniqueID());
+
+ if (useSplitDwarf()) {
+ NewCU.setSkeleton(constructSkeletonCU(NewCU));
+ NewCU.setSection(Asm->getObjFileLowering().getDwarfInfoDWOSection());
+ } else {
+ finishUnitAttributes(DIUnit, NewCU);
+ NewCU.setSection(Asm->getObjFileLowering().getDwarfInfoSection());
+ }
CUMap.insert({DIUnit, &NewCU});
- CUDieMap.insert({&Die, &NewCU});
+ CUDieMap.insert({&NewCU.getUnitDie(), &NewCU});
return NewCU;
}
@@ -613,22 +674,21 @@ void DwarfDebug::constructAndAddImportedEntityDIE(DwarfCompileUnit &TheCU,
/// Sort and unique GVEs by comparing their fragment offset.
static SmallVectorImpl<DwarfCompileUnit::GlobalExpr> &
sortGlobalExprs(SmallVectorImpl<DwarfCompileUnit::GlobalExpr> &GVEs) {
- llvm::sort(GVEs.begin(), GVEs.end(),
- [](DwarfCompileUnit::GlobalExpr A,
- DwarfCompileUnit::GlobalExpr B) {
- // Sort order: first null exprs, then exprs without fragment
- // info, then sort by fragment offset in bits.
- // FIXME: Come up with a more comprehensive comparator so
- // the sorting isn't non-deterministic, and so the following
- // std::unique call works correctly.
- if (!A.Expr || !B.Expr)
- return !!B.Expr;
- auto FragmentA = A.Expr->getFragmentInfo();
- auto FragmentB = B.Expr->getFragmentInfo();
- if (!FragmentA || !FragmentB)
- return !!FragmentB;
- return FragmentA->OffsetInBits < FragmentB->OffsetInBits;
- });
+ llvm::sort(
+ GVEs, [](DwarfCompileUnit::GlobalExpr A, DwarfCompileUnit::GlobalExpr B) {
+ // Sort order: first null exprs, then exprs without fragment
+ // info, then sort by fragment offset in bits.
+ // FIXME: Come up with a more comprehensive comparator so
+ // the sorting isn't non-deterministic, and so the following
+ // std::unique call works correctly.
+ if (!A.Expr || !B.Expr)
+ return !!B.Expr;
+ auto FragmentA = A.Expr->getFragmentInfo();
+ auto FragmentB = B.Expr->getFragmentInfo();
+ if (!FragmentA || !FragmentB)
+ return !!FragmentB;
+ return FragmentA->OffsetInBits < FragmentB->OffsetInBits;
+ });
GVEs.erase(std::unique(GVEs.begin(), GVEs.end(),
[](DwarfCompileUnit::GlobalExpr A,
DwarfCompileUnit::GlobalExpr B) {
@@ -644,15 +704,18 @@ sortGlobalExprs(SmallVectorImpl<DwarfCompileUnit::GlobalExpr> &GVEs) {
void DwarfDebug::beginModule() {
NamedRegionTimer T(DbgTimerName, DbgTimerDescription, DWARFGroupName,
DWARFGroupDescription, TimePassesIsEnabled);
- if (DisableDebugInfoPrinting)
+ if (DisableDebugInfoPrinting) {
+ MMI->setDebugInfoAvailability(false);
return;
+ }
const Module *M = MMI->getModule();
unsigned NumDebugCUs = std::distance(M->debug_compile_units_begin(),
M->debug_compile_units_end());
// Tell MMI whether we have debug info.
- MMI->setDebugInfoAvailability(NumDebugCUs > 0);
+ assert(MMI->hasDebugInfo() == (NumDebugCUs > 0) &&
+ "DebugInfoAvailabilty initialized unexpectedly");
SingleCU = NumDebugCUs == 1;
DenseMap<DIGlobalVariable *, SmallVector<DwarfCompileUnit::GlobalExpr, 1>>
GVMap;
@@ -670,11 +733,24 @@ void DwarfDebug::beginModule() {
(useSplitDwarf() ? SkeletonHolder : InfoHolder)
.setStringOffsetsStartSym(Asm->createTempSymbol("str_offsets_base"));
- // Create the symbol that designates the start of the DWARF v5 range list
- // table. It is located past the header and before the offsets table.
- if (getDwarfVersion() >= 5)
- (useSplitDwarf() ? SkeletonHolder : InfoHolder)
- .setRnglistsTableBaseSym(Asm->createTempSymbol("rnglists_table_base"));
+
+ // Create the symbols that designates the start of the DWARF v5 range list
+ // and locations list tables. They are located past the table headers.
+ if (getDwarfVersion() >= 5) {
+ DwarfFile &Holder = useSplitDwarf() ? SkeletonHolder : InfoHolder;
+ Holder.setRnglistsTableBaseSym(
+ Asm->createTempSymbol("rnglists_table_base"));
+ Holder.setLoclistsTableBaseSym(
+ Asm->createTempSymbol("loclists_table_base"));
+
+ if (useSplitDwarf())
+ InfoHolder.setRnglistsTableBaseSym(
+ Asm->createTempSymbol("rnglists_dwo_table_base"));
+ }
+
+ // Create the symbol that points to the first entry following the debug
+ // address table (.debug_addr) header.
+ AddrPool.setLabel(Asm->createTempSymbol("addr_table_base"));
for (DICompileUnit *CUNode : M->debug_compile_units()) {
// FIXME: Move local imported entities into a list attached to the
@@ -728,16 +804,16 @@ void DwarfDebug::beginModule() {
}
}
-void DwarfDebug::finishVariableDefinitions() {
- for (const auto &Var : ConcreteVariables) {
- DIE *VariableDie = Var->getDIE();
- assert(VariableDie);
+void DwarfDebug::finishEntityDefinitions() {
+ for (const auto &Entity : ConcreteEntities) {
+ DIE *Die = Entity->getDIE();
+ assert(Die);
// FIXME: Consider the time-space tradeoff of just storing the unit pointer
- // in the ConcreteVariables list, rather than looking it up again here.
+ // in the ConcreteEntities list, rather than looking it up again here.
// DIE::getUnit isn't simple - it walks parent pointers, etc.
- DwarfCompileUnit *Unit = CUDieMap.lookup(VariableDie->getUnitDie());
+ DwarfCompileUnit *Unit = CUDieMap.lookup(Die->getUnitDie());
assert(Unit);
- Unit->finishVariableDefinition(*Var);
+ Unit->finishEntityDefinition(Entity.get());
}
}
@@ -755,7 +831,7 @@ void DwarfDebug::finalizeModuleInfo() {
finishSubprogramDefinitions();
- finishVariableDefinitions();
+ finishEntityDefinitions();
// Include the DWO file name in the hash if there's more than one CU.
// This handles ThinLTO's situation where imported CUs may very easily be
@@ -768,6 +844,8 @@ void DwarfDebug::finalizeModuleInfo() {
// all other generation.
for (const auto &P : CUMap) {
auto &TheCU = *P.second;
+ if (TheCU.getCUNode()->isDebugDirectivesOnly())
+ continue;
// Emit DW_AT_containing_type attribute to connect types with their
// vtable holding type.
TheCU.constructContainingTypeDIEs();
@@ -776,7 +854,12 @@ void DwarfDebug::finalizeModuleInfo() {
// If we're splitting the dwarf out now that we've got the entire
// CU then add the dwo id to it.
auto *SkCU = TheCU.getSkeleton();
- if (useSplitDwarf()) {
+ if (useSplitDwarf() && !empty(TheCU.getUnitDie().children())) {
+ finishUnitAttributes(TheCU.getCUNode(), TheCU);
+ TheCU.addString(TheCU.getUnitDie(), dwarf::DW_AT_GNU_dwo_name,
+ Asm->TM.Options.MCOptions.SplitDwarfFile);
+ SkCU->addString(SkCU->getUnitDie(), dwarf::DW_AT_GNU_dwo_name,
+ Asm->TM.Options.MCOptions.SplitDwarfFile);
// Emit a unique identifier for this CU.
uint64_t ID =
DIEHash(Asm).computeCUSignature(DWOName, TheCU.getUnitDie());
@@ -789,18 +872,14 @@ void DwarfDebug::finalizeModuleInfo() {
SkCU->addUInt(SkCU->getUnitDie(), dwarf::DW_AT_GNU_dwo_id,
dwarf::DW_FORM_data8, ID);
}
- // We don't keep track of which addresses are used in which CU so this
- // is a bit pessimistic under LTO.
- if (!AddrPool.isEmpty()) {
- const MCSymbol *Sym = TLOF.getDwarfAddrSection()->getBeginSymbol();
- SkCU->addSectionLabel(SkCU->getUnitDie(), dwarf::DW_AT_GNU_addr_base,
- Sym, Sym);
- }
- if (getDwarfVersion() < 5 && !SkCU->getRangeLists().empty()) {
+
+ if (getDwarfVersion() < 5 && !SkeletonHolder.getRangeLists().empty()) {
const MCSymbol *Sym = TLOF.getDwarfRangesSection()->getBeginSymbol();
SkCU->addSectionLabel(SkCU->getUnitDie(), dwarf::DW_AT_GNU_ranges_base,
Sym, Sym);
}
+ } else if (SkCU) {
+ finishUnitAttributes(SkCU->getCUNode(), *SkCU);
}
// If we have code split among multiple sections or non-contiguous
@@ -810,6 +889,14 @@ void DwarfDebug::finalizeModuleInfo() {
// .subsections_via_symbols in mach-o. This would mean turning on
// 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
@@ -822,9 +909,13 @@ void DwarfDebug::finalizeModuleInfo() {
U.attachRangesOrLowHighPC(U.getUnitDie(), TheCU.takeRanges());
}
- if (getDwarfVersion() >= 5 && !useSplitDwarf() &&
- !U.getRangeLists().empty())
- U.addRnglistsBase();
+ if (getDwarfVersion() >= 5) {
+ if (U.hasRangeLists())
+ U.addRnglistsBase();
+
+ if (!DebugLocs.getLists().empty() && !useSplitDwarf())
+ U.addLoclistsBase();
+ }
auto *CUNode = cast<DICompileUnit>(P.first);
// If compile Unit has macros, emit "DW_AT_macro_info" attribute.
@@ -888,9 +979,11 @@ void DwarfDebug::endModule() {
emitDebugInfoDWO();
emitDebugAbbrevDWO();
emitDebugLineDWO();
- emitDebugAddr();
+ emitDebugRangesDWO();
}
+ emitDebugAddr();
+
// Emit info into the dwarf accelerator table sections.
switch (getAccelTableKind()) {
case AccelTableKind::Apple:
@@ -915,38 +1008,37 @@ void DwarfDebug::endModule() {
// FIXME: AbstractVariables.clear();
}
-void DwarfDebug::ensureAbstractVariableIsCreated(DwarfCompileUnit &CU, InlinedVariable IV,
- const MDNode *ScopeNode) {
- const DILocalVariable *Cleansed = nullptr;
- if (CU.getExistingAbstractVariable(IV, Cleansed))
+void DwarfDebug::ensureAbstractEntityIsCreated(DwarfCompileUnit &CU,
+ const DINode *Node,
+ const MDNode *ScopeNode) {
+ if (CU.getExistingAbstractEntity(Node))
return;
- CU.createAbstractVariable(Cleansed, LScopes.getOrCreateAbstractScope(
+ CU.createAbstractEntity(Node, LScopes.getOrCreateAbstractScope(
cast<DILocalScope>(ScopeNode)));
}
-void DwarfDebug::ensureAbstractVariableIsCreatedIfScoped(DwarfCompileUnit &CU,
- InlinedVariable IV, const MDNode *ScopeNode) {
- const DILocalVariable *Cleansed = nullptr;
- if (CU.getExistingAbstractVariable(IV, Cleansed))
+void DwarfDebug::ensureAbstractEntityIsCreatedIfScoped(DwarfCompileUnit &CU,
+ const DINode *Node, const MDNode *ScopeNode) {
+ if (CU.getExistingAbstractEntity(Node))
return;
if (LexicalScope *Scope =
LScopes.findAbstractScope(cast_or_null<DILocalScope>(ScopeNode)))
- CU.createAbstractVariable(Cleansed, Scope);
+ CU.createAbstractEntity(Node, Scope);
}
// Collect variable information from side table maintained by MF.
void DwarfDebug::collectVariableInfoFromMFTable(
- DwarfCompileUnit &TheCU, DenseSet<InlinedVariable> &Processed) {
- SmallDenseMap<InlinedVariable, DbgVariable *> MFVars;
+ DwarfCompileUnit &TheCU, DenseSet<InlinedEntity> &Processed) {
+ SmallDenseMap<InlinedEntity, DbgVariable *> MFVars;
for (const auto &VI : Asm->MF->getVariableDbgInfo()) {
if (!VI.Var)
continue;
assert(VI.Var->isValidLocationForIntrinsic(VI.Loc) &&
"Expected inlined-at fields to agree");
- InlinedVariable Var(VI.Var, VI.Loc->getInlinedAt());
+ InlinedEntity Var(VI.Var, VI.Loc->getInlinedAt());
Processed.insert(Var);
LexicalScope *Scope = LScopes.findLexicalScope(VI.Loc);
@@ -954,14 +1046,15 @@ void DwarfDebug::collectVariableInfoFromMFTable(
if (!Scope)
continue;
- ensureAbstractVariableIsCreatedIfScoped(TheCU, Var, Scope->getScopeNode());
- auto RegVar = llvm::make_unique<DbgVariable>(Var.first, Var.second);
+ ensureAbstractEntityIsCreatedIfScoped(TheCU, Var.first, Scope->getScopeNode());
+ auto RegVar = llvm::make_unique<DbgVariable>(
+ cast<DILocalVariable>(Var.first), Var.second);
RegVar->initializeMMI(VI.Expr, VI.Slot);
if (DbgVariable *DbgVar = MFVars.lookup(Var))
DbgVar->addMMIEntry(*RegVar);
else if (InfoHolder.addScopeVariable(Scope, RegVar.get())) {
MFVars.insert({Var, RegVar.get()});
- ConcreteVariables.push_back(std::move(RegVar));
+ ConcreteEntities.push_back(std::move(RegVar));
}
}
}
@@ -1087,6 +1180,18 @@ DwarfDebug::buildLocationList(SmallVectorImpl<DebugLocEntry> &DebugLoc,
LLVM_DEBUG(dbgs() << "DotDebugLoc: " << *Begin << "\n");
auto Value = getDebugLocValue(Begin);
+
+ // 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;
@@ -1126,14 +1231,26 @@ DwarfDebug::buildLocationList(SmallVectorImpl<DebugLocEntry> &DebugLoc,
}
}
-DbgVariable *DwarfDebug::createConcreteVariable(DwarfCompileUnit &TheCU,
- LexicalScope &Scope,
- InlinedVariable IV) {
- ensureAbstractVariableIsCreatedIfScoped(TheCU, IV, Scope.getScopeNode());
- ConcreteVariables.push_back(
- llvm::make_unique<DbgVariable>(IV.first, IV.second));
- InfoHolder.addScopeVariable(&Scope, ConcreteVariables.back().get());
- return ConcreteVariables.back().get();
+DbgEntity *DwarfDebug::createConcreteEntity(DwarfCompileUnit &TheCU,
+ LexicalScope &Scope,
+ const DINode *Node,
+ const DILocation *Location,
+ const MCSymbol *Sym) {
+ ensureAbstractEntityIsCreatedIfScoped(TheCU, Node, Scope.getScopeNode());
+ if (isa<const DILocalVariable>(Node)) {
+ ConcreteEntities.push_back(
+ llvm::make_unique<DbgVariable>(cast<const DILocalVariable>(Node),
+ Location));
+ InfoHolder.addScopeVariable(&Scope,
+ cast<DbgVariable>(ConcreteEntities.back().get()));
+ } else if (isa<const DILabel>(Node)) {
+ ConcreteEntities.push_back(
+ llvm::make_unique<DbgLabel>(cast<const DILabel>(Node),
+ Location, Sym));
+ InfoHolder.addScopeLabel(&Scope,
+ cast<DbgLabel>(ConcreteEntities.back().get()));
+ }
+ return ConcreteEntities.back().get();
}
/// Determine whether a *singular* DBG_VALUE is valid for the entirety of its
@@ -1195,14 +1312,14 @@ static bool validThroughout(LexicalScopes &LScopes,
}
// Find variables for each lexical scope.
-void DwarfDebug::collectVariableInfo(DwarfCompileUnit &TheCU,
- const DISubprogram *SP,
- DenseSet<InlinedVariable> &Processed) {
+void DwarfDebug::collectEntityInfo(DwarfCompileUnit &TheCU,
+ const DISubprogram *SP,
+ DenseSet<InlinedEntity> &Processed) {
// Grab the variable info that was squirreled away in the MMI side-table.
collectVariableInfoFromMFTable(TheCU, Processed);
for (const auto &I : DbgValues) {
- InlinedVariable IV = I.first;
+ InlinedEntity IV = I.first;
if (Processed.count(IV))
continue;
@@ -1212,16 +1329,18 @@ void DwarfDebug::collectVariableInfo(DwarfCompileUnit &TheCU,
continue;
LexicalScope *Scope = nullptr;
+ const DILocalVariable *LocalVar = cast<DILocalVariable>(IV.first);
if (const DILocation *IA = IV.second)
- Scope = LScopes.findInlinedScope(IV.first->getScope(), IA);
+ Scope = LScopes.findInlinedScope(LocalVar->getScope(), IA);
else
- Scope = LScopes.findLexicalScope(IV.first->getScope());
+ Scope = LScopes.findLexicalScope(LocalVar->getScope());
// If variable scope is not found then skip this variable.
if (!Scope)
continue;
Processed.insert(IV);
- DbgVariable *RegVar = createConcreteVariable(TheCU, *Scope, IV);
+ DbgVariable *RegVar = cast<DbgVariable>(createConcreteEntity(TheCU,
+ *Scope, LocalVar, IV.second));
const MachineInstr *MInsn = Ranges.front().first;
assert(MInsn->isDebugValue() && "History must begin with debug value");
@@ -1247,20 +1366,53 @@ void DwarfDebug::collectVariableInfo(DwarfCompileUnit &TheCU,
// unique identifiers, so don't bother resolving the type with the
// identifier map.
const DIBasicType *BT = dyn_cast<DIBasicType>(
- static_cast<const Metadata *>(IV.first->getType()));
+ static_cast<const Metadata *>(LocalVar->getType()));
// Finalize the entry by lowering it into a DWARF bytestream.
for (auto &Entry : Entries)
Entry.finalize(*Asm, List, BT);
}
- // Collect info for variables that were optimized out.
+ // For each InlinedEntity collected from DBG_LABEL instructions, convert to
+ // DWARF-related DbgLabel.
+ for (const auto &I : DbgLabels) {
+ InlinedEntity IL = I.first;
+ const MachineInstr *MI = I.second;
+ if (MI == nullptr)
+ continue;
+
+ LexicalScope *Scope = nullptr;
+ const DILabel *Label = cast<DILabel>(IL.first);
+ // Get inlined DILocation if it is inlined label.
+ if (const DILocation *IA = IL.second)
+ Scope = LScopes.findInlinedScope(Label->getScope(), IA);
+ else
+ Scope = LScopes.findLexicalScope(Label->getScope());
+ // If label scope is not found then skip this label.
+ if (!Scope)
+ continue;
+
+ Processed.insert(IL);
+ /// At this point, the temporary label is created.
+ /// Save the temporary label to DbgLabel entity to get the
+ /// actually address when generating Dwarf DIE.
+ MCSymbol *Sym = getLabelBeforeInsn(MI);
+ createConcreteEntity(TheCU, *Scope, Label, IL.second, Sym);
+ }
+
+ // Collect info for variables/labels that were optimized out.
for (const DINode *DN : SP->getRetainedNodes()) {
+ if (!Processed.insert(InlinedEntity(DN, nullptr)).second)
+ continue;
+ LexicalScope *Scope = nullptr;
if (auto *DV = dyn_cast<DILocalVariable>(DN)) {
- if (Processed.insert(InlinedVariable(DV, nullptr)).second)
- if (LexicalScope *Scope = LScopes.findLexicalScope(DV->getScope()))
- createConcreteVariable(TheCU, *Scope, InlinedVariable(DV, nullptr));
+ Scope = LScopes.findLexicalScope(DV->getScope());
+ } else if (auto *DL = dyn_cast<DILabel>(DN)) {
+ Scope = LScopes.findLexicalScope(DL->getScope());
}
+
+ if (Scope)
+ createConcreteEntity(TheCU, *Scope, DN, nullptr);
}
}
@@ -1284,6 +1436,11 @@ void DwarfDebug::beginInstruction(const MachineInstr *MI) {
unsigned LastAsmLine =
Asm->OutStreamer->getContext().getCurrentDwarfLoc().getLine();
+ // Request a label after the call in order to emit AT_return_pc information
+ // in call site entries. TODO: Add support for targets with delay slots.
+ if (SP->areAllCallsDescribed() && MI->isCall() && !MI->hasDelaySlot())
+ requestLabelAfterInsn(MI);
+
if (DL == PrevInstLoc) {
// If we have an ongoing unspecified location, nothing to do here.
if (!DL)
@@ -1416,9 +1573,14 @@ void DwarfDebug::endFunctionImpl(const MachineFunction *MF) {
LexicalScope *FnScope = LScopes.getCurrentFunctionScope();
assert(!FnScope || SP == FnScope->getScopeNode());
DwarfCompileUnit &TheCU = *CUMap.lookup(SP->getUnit());
+ if (TheCU.getCUNode()->isDebugDirectivesOnly()) {
+ PrevLabel = nullptr;
+ CurFn = nullptr;
+ return;
+ }
- DenseSet<InlinedVariable> ProcessedVars;
- collectVariableInfo(TheCU, SP, ProcessedVars);
+ DenseSet<InlinedEntity> Processed;
+ collectEntityInfo(TheCU, SP, Processed);
// Add the range of this function to the list of ranges for the CU.
TheCU.addRange(RangeSpan(Asm->getFunctionBegin(), Asm->getFunctionEnd()));
@@ -1442,31 +1604,41 @@ void DwarfDebug::endFunctionImpl(const MachineFunction *MF) {
for (LexicalScope *AScope : LScopes.getAbstractScopesList()) {
auto *SP = cast<DISubprogram>(AScope->getScopeNode());
for (const DINode *DN : SP->getRetainedNodes()) {
- if (auto *DV = dyn_cast<DILocalVariable>(DN)) {
- // Collect info for variables that were optimized out.
- if (!ProcessedVars.insert(InlinedVariable(DV, nullptr)).second)
- continue;
- ensureAbstractVariableIsCreated(TheCU, InlinedVariable(DV, nullptr),
- DV->getScope());
- assert(LScopes.getAbstractScopesList().size() == NumAbstractScopes
- && "ensureAbstractVariableIsCreated inserted abstract scopes");
- }
+ if (!Processed.insert(InlinedEntity(DN, nullptr)).second)
+ continue;
+
+ const MDNode *Scope = nullptr;
+ if (auto *DV = dyn_cast<DILocalVariable>(DN))
+ Scope = DV->getScope();
+ else if (auto *DL = dyn_cast<DILabel>(DN))
+ Scope = DL->getScope();
+ else
+ llvm_unreachable("Unexpected DI type!");
+
+ // Collect info for variables/labels that were optimized out.
+ ensureAbstractEntityIsCreated(TheCU, DN, Scope);
+ assert(LScopes.getAbstractScopesList().size() == NumAbstractScopes
+ && "ensureAbstractEntityIsCreated inserted abstract scopes");
}
constructAbstractSubprogramScopeDIE(TheCU, AScope);
}
ProcessedSPNodes.insert(SP);
- TheCU.constructSubprogramScopeDIE(SP, FnScope);
+ DIE &ScopeDIE = TheCU.constructSubprogramScopeDIE(SP, FnScope);
if (auto *SkelCU = TheCU.getSkeleton())
if (!LScopes.getAbstractScopesList().empty() &&
TheCU.getCUNode()->getSplitDebugInlining())
SkelCU->constructSubprogramScopeDIE(SP, FnScope);
+ // Construct call site entries.
+ constructCallSiteEntryDIEs(*SP, TheCU, ScopeDIE, *MF);
+
// Clear debug info
// Ownership of DbgVariables is a bit subtle - ScopeVariables owns all the
// DbgVariables except those that are also in AbstractVariables (since they
// can be used cross-function)
InfoHolder.getScopeVariables().clear();
+ InfoHolder.getScopeLabels().clear();
PrevLabel = nullptr;
CurFn = nullptr;
}
@@ -1530,8 +1702,6 @@ void DwarfDebug::emitAccelDebugNames() {
if (getUnits().empty())
return;
- Asm->OutStreamer->SwitchSection(
- Asm->getObjFileLowering().getDwarfDebugNamesSection());
emitDWARF5AccelTable(Asm, AccelDebugNames, *this, getUnits());
}
@@ -1636,7 +1806,8 @@ void DwarfDebug::emitDebugPubSections() {
if (!TheU->hasDwarfPubSections())
continue;
- bool GnuStyle = TheU->getCUNode()->getGnuPubnames();
+ bool GnuStyle = TheU->getCUNode()->getNameTableKind() ==
+ DICompileUnit::DebugNameTableKind::GNU;
Asm->OutStreamer->SwitchSection(
GnuStyle ? Asm->getObjFileLowering().getDwarfGnuPubNamesSection()
@@ -1692,8 +1863,8 @@ void DwarfDebug::emitDebugPubSection(bool GnuStyle, StringRef Name,
if (GnuStyle) {
dwarf::PubIndexEntryDescriptor Desc = computeIndexValue(TheU, Entity);
Asm->OutStreamer->AddComment(
- Twine("Kind: ") + dwarf::GDBIndexEntryKindString(Desc.Kind) + ", " +
- dwarf::GDBIndexEntryLinkageString(Desc.Linkage));
+ Twine("Attributes: ") + dwarf::GDBIndexEntryKindString(Desc.Kind) +
+ ", " + dwarf::GDBIndexEntryLinkageString(Desc.Linkage));
Asm->emitInt8(Desc.toBits());
}
@@ -1759,6 +1930,7 @@ static void emitDebugLocValue(const AsmPrinter &AP, const DIBasicType *BT,
void DebugLocEntry::finalize(const AsmPrinter &AP,
DebugLocStream::ListBuilder &List,
const DIBasicType *BT) {
+ 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);
@@ -1791,25 +1963,119 @@ void DwarfDebug::emitDebugLocEntryLocation(const DebugLocStream::Entry &Entry) {
emitDebugLocEntry(Streamer, Entry);
}
-// Emit locations into the debug loc section.
+// Emit the common part of the DWARF 5 range/locations list tables header.
+static void emitListsTableHeaderStart(AsmPrinter *Asm, const DwarfFile &Holder,
+ MCSymbol *TableStart,
+ MCSymbol *TableEnd) {
+ // Build the table header, which starts with the length field.
+ Asm->OutStreamer->AddComment("Length");
+ Asm->EmitLabelDifference(TableEnd, TableStart, 4);
+ Asm->OutStreamer->EmitLabel(TableStart);
+ // Version number (DWARF v5 and later).
+ Asm->OutStreamer->AddComment("Version");
+ Asm->emitInt16(Asm->OutStreamer->getContext().getDwarfVersion());
+ // Address size.
+ Asm->OutStreamer->AddComment("Address size");
+ Asm->emitInt8(Asm->MAI->getCodePointerSize());
+ // Segment selector size.
+ Asm->OutStreamer->AddComment("Segment selector size");
+ Asm->emitInt8(0);
+}
+
+// Emit the header of a DWARF 5 range list table list table. Returns the symbol
+// that designates the end of the table for the caller to emit when the table is
+// complete.
+static MCSymbol *emitRnglistsTableHeader(AsmPrinter *Asm,
+ const DwarfFile &Holder) {
+ MCSymbol *TableStart = Asm->createTempSymbol("debug_rnglist_table_start");
+ MCSymbol *TableEnd = Asm->createTempSymbol("debug_rnglist_table_end");
+ emitListsTableHeaderStart(Asm, Holder, TableStart, TableEnd);
+
+ Asm->OutStreamer->AddComment("Offset entry count");
+ Asm->emitInt32(Holder.getRangeLists().size());
+ Asm->OutStreamer->EmitLabel(Holder.getRnglistsTableBaseSym());
+
+ for (const RangeSpanList &List : Holder.getRangeLists())
+ Asm->EmitLabelDifference(List.getSym(), Holder.getRnglistsTableBaseSym(),
+ 4);
+
+ return TableEnd;
+}
+
+// Emit the header of a DWARF 5 locations list table. Returns the symbol that
+// designates the end of the table for the caller to emit when the table is
+// complete.
+static MCSymbol *emitLoclistsTableHeader(AsmPrinter *Asm,
+ const DwarfFile &Holder) {
+ MCSymbol *TableStart = Asm->createTempSymbol("debug_loclist_table_start");
+ MCSymbol *TableEnd = Asm->createTempSymbol("debug_loclist_table_end");
+ emitListsTableHeaderStart(Asm, Holder, TableStart, TableEnd);
+
+ // FIXME: Generate the offsets table and use DW_FORM_loclistx with the
+ // DW_AT_loclists_base attribute. Until then set the number of offsets to 0.
+ Asm->OutStreamer->AddComment("Offset entry count");
+ Asm->emitInt32(0);
+ Asm->OutStreamer->EmitLabel(Holder.getLoclistsTableBaseSym());
+
+ return TableEnd;
+}
+
+// Emit locations into the .debug_loc/.debug_rnglists section.
void DwarfDebug::emitDebugLoc() {
if (DebugLocs.getLists().empty())
return;
- // Start the dwarf loc section.
- Asm->OutStreamer->SwitchSection(
- Asm->getObjFileLowering().getDwarfLocSection());
+ bool IsLocLists = getDwarfVersion() >= 5;
+ MCSymbol *TableEnd = nullptr;
+ if (IsLocLists) {
+ Asm->OutStreamer->SwitchSection(
+ Asm->getObjFileLowering().getDwarfLoclistsSection());
+ TableEnd = emitLoclistsTableHeader(Asm, useSplitDwarf() ? SkeletonHolder
+ : InfoHolder);
+ } else {
+ Asm->OutStreamer->SwitchSection(
+ Asm->getObjFileLowering().getDwarfLocSection());
+ }
+
unsigned char Size = Asm->MAI->getCodePointerSize();
for (const auto &List : DebugLocs.getLists()) {
Asm->OutStreamer->EmitLabel(List.Label);
+
const DwarfCompileUnit *CU = List.CU;
+ const MCSymbol *Base = CU->getBaseAddress();
for (const auto &Entry : DebugLocs.getEntries(List)) {
- // Set up the range. This range is relative to the entry point of the
- // compile unit. This is a hard coded 0 for low_pc when we're emitting
- // ranges, or the DW_AT_low_pc on the compile unit otherwise.
- if (auto *Base = CU->getBaseAddress()) {
- Asm->EmitLabelDifference(Entry.BeginSym, Base, Size);
- Asm->EmitLabelDifference(Entry.EndSym, Base, Size);
+ if (Base) {
+ // Set up the range. This range is relative to the entry point of the
+ // compile unit. This is a hard coded 0 for low_pc when we're emitting
+ // ranges, or the DW_AT_low_pc on the compile unit otherwise.
+ if (IsLocLists) {
+ Asm->OutStreamer->AddComment("DW_LLE_offset_pair");
+ Asm->OutStreamer->EmitIntValue(dwarf::DW_LLE_offset_pair, 1);
+ Asm->OutStreamer->AddComment(" starting offset");
+ Asm->EmitLabelDifferenceAsULEB128(Entry.BeginSym, Base);
+ Asm->OutStreamer->AddComment(" ending offset");
+ Asm->EmitLabelDifferenceAsULEB128(Entry.EndSym, Base);
+ } else {
+ Asm->EmitLabelDifference(Entry.BeginSym, Base, Size);
+ Asm->EmitLabelDifference(Entry.EndSym, Base, Size);
+ }
+
+ emitDebugLocEntryLocation(Entry);
+ continue;
+ }
+
+ // We have no base address.
+ if (IsLocLists) {
+ // TODO: Use DW_LLE_base_addressx + DW_LLE_offset_pair, or
+ // DW_LLE_startx_length in case if there is only a single range.
+ // That should reduce the size of the debug data emited.
+ // For now just use the DW_LLE_startx_length for all cases.
+ Asm->OutStreamer->AddComment("DW_LLE_startx_length");
+ Asm->emitInt8(dwarf::DW_LLE_startx_length);
+ Asm->OutStreamer->AddComment(" start idx");
+ Asm->EmitULEB128(AddrPool.getIndex(Entry.BeginSym));
+ Asm->OutStreamer->AddComment(" length");
+ Asm->EmitLabelDifferenceAsULEB128(Entry.EndSym, Entry.BeginSym);
} else {
Asm->OutStreamer->EmitSymbolValue(Entry.BeginSym, Size);
Asm->OutStreamer->EmitSymbolValue(Entry.EndSym, Size);
@@ -1817,9 +2083,20 @@ void DwarfDebug::emitDebugLoc() {
emitDebugLocEntryLocation(Entry);
}
- Asm->OutStreamer->EmitIntValue(0, Size);
- Asm->OutStreamer->EmitIntValue(0, Size);
+
+ if (IsLocLists) {
+ // .debug_loclists section ends with DW_LLE_end_of_list.
+ Asm->OutStreamer->AddComment("DW_LLE_end_of_list");
+ Asm->OutStreamer->EmitIntValue(dwarf::DW_LLE_end_of_list, 1);
+ } else {
+ // Terminate the .debug_loc list with two 0 values.
+ Asm->OutStreamer->EmitIntValue(0, Size);
+ Asm->OutStreamer->EmitIntValue(0, Size);
+ }
}
+
+ if (TableEnd)
+ Asm->OutStreamer->EmitLabel(TableEnd);
}
void DwarfDebug::emitDebugLocDWO() {
@@ -1828,10 +2105,13 @@ void DwarfDebug::emitDebugLocDWO() {
for (const auto &List : DebugLocs.getLists()) {
Asm->OutStreamer->EmitLabel(List.Label);
for (const auto &Entry : DebugLocs.getEntries(List)) {
- // Just always use start_length for now - at least that's one address
- // rather than two. We could get fancier and try to, say, reuse an
- // address we know we've emitted elsewhere (the start of the function?
- // The start of the CU or CU subrange that encloses this range?)
+ // GDB only supports startx_length in pre-standard split-DWARF.
+ // (in v5 standard loclists, it currently* /only/ supports base_address +
+ // offset_pair, so the implementations can't really share much since they
+ // need to use different representations)
+ // * as of October 2018, at least
+ // Ideally/in v5, this could use SectionLabels to reuse existing addresses
+ // in the address pool to minimize object size/relocations.
Asm->emitInt8(dwarf::DW_LLE_startx_length);
unsigned idx = AddrPool.getIndex(Entry.BeginSym);
Asm->EmitULEB128(idx);
@@ -1939,10 +2219,9 @@ void DwarfDebug::emitDebugARanges() {
}
// Sort the CU list (again, to ensure consistent output order).
- llvm::sort(CUs.begin(), CUs.end(),
- [](const DwarfCompileUnit *A, const DwarfCompileUnit *B) {
- return A->getUniqueID() < B->getUniqueID();
- });
+ llvm::sort(CUs, [](const DwarfCompileUnit *A, const DwarfCompileUnit *B) {
+ return A->getUniqueID() < B->getUniqueID();
+ });
// Emit an arange table for each CU we used.
for (DwarfCompileUnit *CU : CUs) {
@@ -2006,10 +2285,10 @@ void DwarfDebug::emitDebugARanges() {
}
/// Emit a single range list. We handle both DWARF v5 and earlier.
-static void emitRangeList(AsmPrinter *Asm, DwarfCompileUnit *CU,
+static void emitRangeList(DwarfDebug &DD, AsmPrinter *Asm,
const RangeSpanList &List) {
- auto DwarfVersion = CU->getDwarfVersion();
+ auto DwarfVersion = DD.getDwarfVersion();
// Emit our symbol so we can find the beginning of the range.
Asm->OutStreamer->EmitLabel(List.getSym());
// Gather all the ranges that apply to the same section so they can share
@@ -2021,7 +2300,8 @@ static void emitRangeList(AsmPrinter *Asm, DwarfCompileUnit *CU,
for (const RangeSpan &Range : List.getRanges())
SectionRanges[&Range.getStart()->getSection()].push_back(&Range);
- auto *CUBase = CU->getBaseAddress();
+ const DwarfCompileUnit &CU = List.getCU();
+ const MCSymbol *CUBase = CU.getBaseAddress();
bool BaseIsSet = false;
for (const auto &P : SectionRanges) {
// Don't bother with a base address entry if there's only one range in
@@ -2031,19 +2311,23 @@ static void emitRangeList(AsmPrinter *Asm, DwarfCompileUnit *CU,
// or optnone where there may be holes in a single CU's section
// contributions.
auto *Base = CUBase;
- if (!Base && P.second.size() > 1 &&
- (UseDwarfRangesBaseAddressSpecifier || DwarfVersion >= 5)) {
+ if (!Base && (P.second.size() > 1 || DwarfVersion < 5) &&
+ (CU.getCUNode()->getRangesBaseAddress() || DwarfVersion >= 5)) {
BaseIsSet = true;
// FIXME/use care: This may not be a useful base address if it's not
// the lowest address/range in this object.
Base = P.second.front()->getStart();
if (DwarfVersion >= 5) {
- Asm->OutStreamer->AddComment("DW_RLE_base_address");
- Asm->OutStreamer->EmitIntValue(dwarf::DW_RLE_base_address, 1);
- } else
+ Base = DD.getSectionLabel(&Base->getSection());
+ Asm->OutStreamer->AddComment("DW_RLE_base_addressx");
+ Asm->OutStreamer->EmitIntValue(dwarf::DW_RLE_base_addressx, 1);
+ Asm->OutStreamer->AddComment(" base address index");
+ Asm->EmitULEB128(DD.getAddressPool().getIndex(Base));
+ } else {
Asm->OutStreamer->EmitIntValue(-1, Size);
- Asm->OutStreamer->AddComment(" base address");
- Asm->OutStreamer->EmitSymbolValue(Base, Size);
+ Asm->OutStreamer->AddComment(" base address");
+ Asm->OutStreamer->EmitSymbolValue(Base, Size);
+ }
} else if (BaseIsSet && DwarfVersion < 5) {
BaseIsSet = false;
assert(!Base);
@@ -2070,10 +2354,10 @@ static void emitRangeList(AsmPrinter *Asm, DwarfCompileUnit *CU,
Asm->EmitLabelDifference(End, Base, Size);
}
} else if (DwarfVersion >= 5) {
- Asm->OutStreamer->AddComment("DW_RLE_start_length");
- Asm->OutStreamer->EmitIntValue(dwarf::DW_RLE_start_length, 1);
- Asm->OutStreamer->AddComment(" start");
- Asm->OutStreamer->EmitSymbolValue(Begin, Size);
+ Asm->OutStreamer->AddComment("DW_RLE_startx_length");
+ Asm->OutStreamer->EmitIntValue(dwarf::DW_RLE_startx_length, 1);
+ Asm->OutStreamer->AddComment(" start index");
+ Asm->EmitULEB128(DD.getAddressPool().getIndex(Begin));
Asm->OutStreamer->AddComment(" length");
Asm->EmitLabelDifferenceAsULEB128(End, Begin);
} else {
@@ -2092,31 +2376,13 @@ static void emitRangeList(AsmPrinter *Asm, DwarfCompileUnit *CU,
}
}
-// Emit the header of a DWARF 5 range list table. Returns the symbol that
-// designates the end of the table for the caller to emit when the table is
-// complete.
-static MCSymbol *emitRnglistsTableHeader(AsmPrinter *Asm, DwarfFile &Holder) {
- // The length is described by a starting label right after the length field
- // and an end label.
- MCSymbol *TableStart = Asm->createTempSymbol("debug_rnglist_table_start");
- MCSymbol *TableEnd = Asm->createTempSymbol("debug_rnglist_table_end");
- // Build the range table header, which starts with the length field.
- Asm->EmitLabelDifference(TableEnd, TableStart, 4);
- Asm->OutStreamer->EmitLabel(TableStart);
- // Version number (DWARF v5 and later).
- Asm->emitInt16(Asm->OutStreamer->getContext().getDwarfVersion());
- // Address size.
- Asm->emitInt8(Asm->MAI->getCodePointerSize());
- // Segment selector size.
- Asm->emitInt8(0);
-
- MCSymbol *RnglistTableBaseSym = Holder.getRnglistsTableBaseSym();
+static void emitDebugRangesImpl(DwarfDebug &DD, AsmPrinter *Asm,
+ const DwarfFile &Holder, MCSymbol *TableEnd) {
+ for (const RangeSpanList &List : Holder.getRangeLists())
+ emitRangeList(DD, Asm, List);
- // FIXME: Generate the offsets table and use DW_FORM_rnglistx with the
- // DW_AT_ranges attribute. Until then set the number of offsets to 0.
- Asm->emitInt32(0);
- Asm->OutStreamer->EmitLabel(RnglistTableBaseSym);
- return TableEnd;
+ if (TableEnd)
+ Asm->OutStreamer->EmitLabel(TableEnd);
}
/// Emit address ranges into the .debug_ranges section or into the DWARF v5
@@ -2125,46 +2391,52 @@ void DwarfDebug::emitDebugRanges() {
if (CUMap.empty())
return;
- auto NoRangesPresent = [this]() {
- return llvm::all_of(
- CUMap, [](const decltype(CUMap)::value_type &Pair) {
- return Pair.second->getRangeLists().empty();
- });
- };
+ const auto &Holder = useSplitDwarf() ? SkeletonHolder : InfoHolder;
- if (!useRangesSection()) {
- assert(NoRangesPresent() && "No debug ranges expected.");
+ if (Holder.getRangeLists().empty())
return;
- }
- if (NoRangesPresent())
- return;
+ assert(useRangesSection());
+ assert(llvm::none_of(CUMap, [](const decltype(CUMap)::value_type &Pair) {
+ return Pair.second->getCUNode()->isDebugDirectivesOnly();
+ }));
// Start the dwarf ranges section.
MCSymbol *TableEnd = nullptr;
if (getDwarfVersion() >= 5) {
Asm->OutStreamer->SwitchSection(
Asm->getObjFileLowering().getDwarfRnglistsSection());
- TableEnd = emitRnglistsTableHeader(Asm, useSplitDwarf() ? SkeletonHolder
- : InfoHolder);
+ TableEnd = emitRnglistsTableHeader(Asm, Holder);
} else
Asm->OutStreamer->SwitchSection(
Asm->getObjFileLowering().getDwarfRangesSection());
- // Grab the specific ranges for the compile units in the module.
- for (const auto &I : CUMap) {
- DwarfCompileUnit *TheCU = I.second;
+ emitDebugRangesImpl(*this, Asm, Holder, TableEnd);
+}
- if (auto *Skel = TheCU->getSkeleton())
- TheCU = Skel;
+void DwarfDebug::emitDebugRangesDWO() {
+ assert(useSplitDwarf());
- // Iterate over the misc ranges for the compile units in the module.
- for (const RangeSpanList &List : TheCU->getRangeLists())
- emitRangeList(Asm, TheCU, List);
- }
+ if (CUMap.empty())
+ return;
- if (TableEnd)
- Asm->OutStreamer->EmitLabel(TableEnd);
+ const auto &Holder = InfoHolder;
+
+ if (Holder.getRangeLists().empty())
+ return;
+
+ assert(getDwarfVersion() >= 5);
+ assert(useRangesSection());
+ assert(llvm::none_of(CUMap, [](const decltype(CUMap)::value_type &Pair) {
+ return Pair.second->getCUNode()->isDebugDirectivesOnly();
+ }));
+
+ // Start the dwarf ranges section.
+ Asm->OutStreamer->SwitchSection(
+ Asm->getObjFileLowering().getDwarfRnglistsDWOSection());
+ MCSymbol *TableEnd = emitRnglistsTableHeader(Asm, Holder);
+
+ emitDebugRangesImpl(*this, Asm, Holder, TableEnd);
}
void DwarfDebug::handleMacroNodes(DIMacroNodeArray Nodes, DwarfCompileUnit &U) {
@@ -2206,12 +2478,19 @@ void DwarfDebug::emitDebugMacinfo() {
if (CUMap.empty())
return;
+ if (llvm::all_of(CUMap, [](const decltype(CUMap)::value_type &Pair) {
+ return Pair.second->getCUNode()->isDebugDirectivesOnly();
+ }))
+ return;
+
// Start the dwarf macinfo section.
Asm->OutStreamer->SwitchSection(
Asm->getObjFileLowering().getDwarfMacinfoSection());
for (const auto &P : CUMap) {
auto &TheCU = *P.second;
+ if (TheCU.getCUNode()->isDebugDirectivesOnly())
+ continue;
auto *SkCU = TheCU.getSkeleton();
DwarfCompileUnit &U = SkCU ? *SkCU : TheCU;
auto *CUNode = cast<DICompileUnit>(P.first);
@@ -2229,8 +2508,6 @@ void DwarfDebug::emitDebugMacinfo() {
void DwarfDebug::initSkeletonUnit(const DwarfUnit &U, DIE &Die,
std::unique_ptr<DwarfCompileUnit> NewU) {
- NewU->addString(Die, dwarf::DW_AT_GNU_dwo_name,
- Asm->TM.Options.MCOptions.SplitDwarfFile);
if (!CompilationDir.empty())
NewU->addString(Die, dwarf::DW_AT_comp_dir, CompilationDir);
@@ -2298,9 +2575,8 @@ void DwarfDebug::emitDebugStrDWO() {
OffSec, /* UseRelativeOffsets = */ false);
}
-// Emit DWO addresses.
+// Emit address pool.
void DwarfDebug::emitDebugAddr() {
- assert(useSplitDwarf() && "No split dwarf?");
AddrPool.emit(*Asm, Asm->getObjFileLowering().getDwarfAddrSection());
}
@@ -2356,10 +2632,18 @@ void DwarfDebug::addDwarfTypeUnitType(DwarfCompileUnit &CU,
NewTU.setTypeSignature(Signature);
Ins.first->second = Signature;
- if (useSplitDwarf())
- NewTU.setSection(Asm->getObjFileLowering().getDwarfTypesDWOSection());
- else {
- NewTU.setSection(Asm->getObjFileLowering().getDwarfTypesSection(Signature));
+ if (useSplitDwarf()) {
+ MCSection *Section =
+ getDwarfVersion() <= 4
+ ? Asm->getObjFileLowering().getDwarfTypesDWOSection()
+ : Asm->getObjFileLowering().getDwarfInfoDWOSection();
+ NewTU.setSection(Section);
+ } else {
+ MCSection *Section =
+ getDwarfVersion() <= 4
+ ? Asm->getObjFileLowering().getDwarfTypesSection(Signature)
+ : Asm->getObjFileLowering().getDwarfInfoSection(Signature);
+ NewTU.setSection(Section);
// Non-split type units reuse the compile unit's line table.
CU.applyStmtList(UnitDie);
}
@@ -2408,14 +2692,18 @@ void DwarfDebug::addDwarfTypeUnitType(DwarfCompileUnit &CU,
// AccelTableKind::Apple, we use the table we got as an argument). If
// accelerator tables are disabled, this function does nothing.
template <typename DataT>
-void DwarfDebug::addAccelNameImpl(AccelTable<DataT> &AppleAccel, StringRef Name,
+void DwarfDebug::addAccelNameImpl(const DICompileUnit &CU,
+ AccelTable<DataT> &AppleAccel, StringRef Name,
const DIE &Die) {
if (getAccelTableKind() == AccelTableKind::None)
return;
+ if (getAccelTableKind() != AccelTableKind::Apple &&
+ CU.getNameTableKind() == DICompileUnit::DebugNameTableKind::None)
+ return;
+
DwarfFile &Holder = useSplitDwarf() ? SkeletonHolder : InfoHolder;
- DwarfStringPoolEntryRef Ref =
- Holder.getStringPool().getEntry(*Asm, Name);
+ DwarfStringPoolEntryRef Ref = Holder.getStringPool().getEntry(*Asm, Name);
switch (getAccelTableKind()) {
case AccelTableKind::Apple:
@@ -2431,24 +2719,36 @@ void DwarfDebug::addAccelNameImpl(AccelTable<DataT> &AppleAccel, StringRef Name,
}
}
-void DwarfDebug::addAccelName(StringRef Name, const DIE &Die) {
- addAccelNameImpl(AccelNames, Name, Die);
+void DwarfDebug::addAccelName(const DICompileUnit &CU, StringRef Name,
+ const DIE &Die) {
+ addAccelNameImpl(CU, AccelNames, Name, Die);
}
-void DwarfDebug::addAccelObjC(StringRef Name, const DIE &Die) {
+void DwarfDebug::addAccelObjC(const DICompileUnit &CU, StringRef Name,
+ const DIE &Die) {
// ObjC names go only into the Apple accelerator tables.
if (getAccelTableKind() == AccelTableKind::Apple)
- addAccelNameImpl(AccelObjC, Name, Die);
+ addAccelNameImpl(CU, AccelObjC, Name, Die);
}
-void DwarfDebug::addAccelNamespace(StringRef Name, const DIE &Die) {
- addAccelNameImpl(AccelNamespace, Name, Die);
+void DwarfDebug::addAccelNamespace(const DICompileUnit &CU, StringRef Name,
+ const DIE &Die) {
+ addAccelNameImpl(CU, AccelNamespace, Name, Die);
}
-void DwarfDebug::addAccelType(StringRef Name, const DIE &Die, char Flags) {
- addAccelNameImpl(AccelTypes, Name, Die);
+void DwarfDebug::addAccelType(const DICompileUnit &CU, StringRef Name,
+ const DIE &Die, char Flags) {
+ addAccelNameImpl(CU, AccelTypes, Name, Die);
}
uint16_t DwarfDebug::getDwarfVersion() const {
return Asm->OutStreamer->getContext().getDwarfVersion();
}
+
+void DwarfDebug::addSectionLabel(const MCSymbol *Sym) {
+ SectionLabels.insert(std::make_pair(&Sym->getSection(), Sym));
+}
+
+const MCSymbol *DwarfDebug::getSectionLabel(const MCSection *S) {
+ return SectionLabels.find(S)->second;
+}
diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h
index abf2e43b1312..8a31e989b289 100644
--- a/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h
+++ b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.h
@@ -15,8 +15,6 @@
#define LLVM_LIB_CODEGEN_ASMPRINTER_DWARFDEBUG_H
#include "AddressPool.h"
-#include "DbgValueHistoryCalculator.h"
-#include "DebugHandlerBase.h"
#include "DebugLocStream.h"
#include "DwarfFile.h"
#include "llvm/ADT/ArrayRef.h"
@@ -31,6 +29,8 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/BinaryFormat/Dwarf.h"
#include "llvm/CodeGen/AccelTable.h"
+#include "llvm/CodeGen/DbgEntityHistoryCalculator.h"
+#include "llvm/CodeGen/DebugHandlerBase.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/IR/DebugInfoMetadata.h"
#include "llvm/IR/DebugLoc.h"
@@ -62,6 +62,47 @@ class MDNode;
class Module;
//===----------------------------------------------------------------------===//
+/// This class is defined as the common parent of DbgVariable and DbgLabel
+/// such that it could levarage polymorphism to extract common code for
+/// DbgVariable and DbgLabel.
+class DbgEntity {
+ const DINode *Entity;
+ const DILocation *InlinedAt;
+ DIE *TheDIE = nullptr;
+ unsigned SubclassID;
+
+public:
+ enum DbgEntityKind {
+ DbgVariableKind,
+ DbgLabelKind
+ };
+
+ DbgEntity(const DINode *N, const DILocation *IA, unsigned ID)
+ : Entity(N), InlinedAt(IA), SubclassID(ID) {}
+ virtual ~DbgEntity() {}
+
+ /// Accessors.
+ /// @{
+ const DINode *getEntity() const { return Entity; }
+ const DILocation *getInlinedAt() const { return InlinedAt; }
+ DIE *getDIE() const { return TheDIE; }
+ unsigned getDbgEntityID() const { return SubclassID; }
+ /// @}
+
+ void setDIE(DIE &D) { TheDIE = &D; }
+
+ static bool classof(const DbgEntity *N) {
+ switch (N->getDbgEntityID()) {
+ default:
+ return false;
+ case DbgVariableKind:
+ case DbgLabelKind:
+ return true;
+ }
+ }
+};
+
+//===----------------------------------------------------------------------===//
/// This class is used to track local variable information.
///
/// Variables can be created from allocas, in which case they're generated from
@@ -73,10 +114,7 @@ class Module;
/// single instruction use \a MInsn and (optionally) a single entry of \a Expr.
///
/// Variables that have been optimized out use none of these fields.
-class DbgVariable {
- const DILocalVariable *Var; /// Variable Descriptor.
- const DILocation *IA; /// Inlined at location.
- DIE *TheDIE = nullptr; /// Variable DIE.
+class DbgVariable : public DbgEntity {
unsigned DebugLocListIndex = ~0u; /// Offset in DebugLocs.
const MachineInstr *MInsn = nullptr; /// DBG_VALUE instruction.
@@ -93,7 +131,7 @@ public:
/// Creates a variable without any DW_AT_location. Call \a initializeMMI()
/// for MMI entries, or \a initializeDbgValue() for DBG_VALUE instructions.
DbgVariable(const DILocalVariable *V, const DILocation *IA)
- : Var(V), IA(IA) {}
+ : DbgEntity(V, IA, DbgVariableKind) {}
/// Initialize from the MMI table.
void initializeMMI(const DIExpression *E, int FI) {
@@ -111,8 +149,9 @@ public:
assert(FrameIndexExprs.empty() && "Already initialized?");
assert(!MInsn && "Already initialized?");
- assert(Var == DbgValue->getDebugVariable() && "Wrong variable");
- assert(IA == DbgValue->getDebugLoc()->getInlinedAt() && "Wrong inlined-at");
+ assert(getVariable() == DbgValue->getDebugVariable() && "Wrong variable");
+ assert(getInlinedAt() == DbgValue->getDebugLoc()->getInlinedAt() &&
+ "Wrong inlined-at");
MInsn = DbgValue;
if (auto *E = DbgValue->getDebugExpression())
@@ -121,19 +160,18 @@ public:
}
// Accessors.
- const DILocalVariable *getVariable() const { return Var; }
- const DILocation *getInlinedAt() const { return IA; }
+ const DILocalVariable *getVariable() const {
+ return cast<DILocalVariable>(getEntity());
+ }
const DIExpression *getSingleExpression() const {
assert(MInsn && FrameIndexExprs.size() <= 1);
return FrameIndexExprs.size() ? FrameIndexExprs[0].Expr : nullptr;
}
- void setDIE(DIE &D) { TheDIE = &D; }
- DIE *getDIE() const { return TheDIE; }
void setDebugLocListIndex(unsigned O) { DebugLocListIndex = O; }
unsigned getDebugLocListIndex() const { return DebugLocListIndex; }
- StringRef getName() const { return Var->getName(); }
+ StringRef getName() const { return getVariable()->getName(); }
const MachineInstr *getMInsn() const { return MInsn; }
/// Get the FI entries, sorted by fragment offset.
ArrayRef<FrameIndexExpr> getFrameIndexExprs() const;
@@ -143,7 +181,7 @@ public:
// Translate tag to proper Dwarf tag.
dwarf::Tag getTag() const {
// FIXME: Why don't we just infer this tag and store it all along?
- if (Var->isParameter())
+ if (getVariable()->isParameter())
return dwarf::DW_TAG_formal_parameter;
return dwarf::DW_TAG_variable;
@@ -151,7 +189,7 @@ public:
/// Return true if DbgVariable is artificial.
bool isArtificial() const {
- if (Var->isArtificial())
+ if (getVariable()->isArtificial())
return true;
if (getType()->isArtificial())
return true;
@@ -159,7 +197,7 @@ public:
}
bool isObjectPointer() const {
- if (Var->isObjectPointer())
+ if (getVariable()->isObjectPointer())
return true;
if (getType()->isObjectPointer())
return true;
@@ -178,6 +216,45 @@ public:
bool isBlockByrefVariable() const;
const DIType *getType() const;
+ static bool classof(const DbgEntity *N) {
+ return N->getDbgEntityID() == DbgVariableKind;
+ }
+
+private:
+ template <typename T> T *resolve(TypedDINodeRef<T> Ref) const {
+ return Ref.resolve();
+ }
+};
+
+//===----------------------------------------------------------------------===//
+/// This class is used to track label information.
+///
+/// Labels are collected from \c DBG_LABEL instructions.
+class DbgLabel : public DbgEntity {
+ const MCSymbol *Sym; /// Symbol before DBG_LABEL instruction.
+
+public:
+ /// We need MCSymbol information to generate DW_AT_low_pc.
+ DbgLabel(const DILabel *L, const DILocation *IA, const MCSymbol *Sym = nullptr)
+ : DbgEntity(L, IA, DbgLabelKind), Sym(Sym) {}
+
+ /// Accessors.
+ /// @{
+ const DILabel *getLabel() const { return cast<DILabel>(getEntity()); }
+ const MCSymbol *getSymbol() const { return Sym; }
+
+ StringRef getName() const { return getLabel()->getName(); }
+ /// @}
+
+ /// Translate tag to proper Dwarf tag.
+ dwarf::Tag getTag() const {
+ return dwarf::DW_TAG_label;
+ }
+
+ static bool classof(const DbgEntity *N) {
+ return N->getDbgEntityID() == DbgLabelKind;
+ }
+
private:
template <typename T> T *resolve(TypedDINodeRef<T> Ref) const {
return Ref.resolve();
@@ -217,8 +294,8 @@ class DwarfDebug : public DebugHandlerBase {
/// Size of each symbol emitted (for those symbols that have a specific size).
DenseMap<const MCSymbol *, uint64_t> SymSize;
- /// Collection of abstract variables.
- SmallVector<std::unique_ptr<DbgVariable>, 64> ConcreteVariables;
+ /// Collection of abstract variables/labels.
+ SmallVector<std::unique_ptr<DbgEntity>, 64> ConcreteEntities;
/// Collection of DebugLocEntry. Stored in a linked list so that DIELocLists
/// can refer to them in spite of insertions into this list.
@@ -250,6 +327,8 @@ class DwarfDebug : public DebugHandlerBase {
/// used to keep track of which types we have emitted type units for.
DenseMap<const MDNode *, uint64_t> TypeSignatures;
+ DenseMap<const MCSection *, const MCSymbol *> SectionLabels;
+
SmallVector<
std::pair<std::unique_ptr<DwarfTypeUnit>, const DICompositeType *>, 1>
TypeUnitsUnderConstruction;
@@ -266,9 +345,6 @@ class DwarfDebug : public DebugHandlerBase {
/// Use inlined strings.
bool UseInlineStrings = false;
- /// Whether to emit DWARF pub sections or not.
- bool UsePubSections = true;
-
/// Allow emission of .debug_ranges section.
bool UseRangesSection = true;
@@ -332,24 +408,33 @@ class DwarfDebug : public DebugHandlerBase {
return InfoHolder.getUnits();
}
- using InlinedVariable = DbgValueHistoryMap::InlinedVariable;
+ using InlinedEntity = DbgValueHistoryMap::InlinedEntity;
- void ensureAbstractVariableIsCreated(DwarfCompileUnit &CU, InlinedVariable IV,
- const MDNode *Scope);
- void ensureAbstractVariableIsCreatedIfScoped(DwarfCompileUnit &CU, InlinedVariable IV,
- const MDNode *Scope);
+ void ensureAbstractEntityIsCreated(DwarfCompileUnit &CU,
+ const DINode *Node,
+ const MDNode *Scope);
+ void ensureAbstractEntityIsCreatedIfScoped(DwarfCompileUnit &CU,
+ const DINode *Node,
+ const MDNode *Scope);
- DbgVariable *createConcreteVariable(DwarfCompileUnit &TheCU,
- LexicalScope &Scope, InlinedVariable IV);
+ DbgEntity *createConcreteEntity(DwarfCompileUnit &TheCU,
+ LexicalScope &Scope,
+ const DINode *Node,
+ const DILocation *Location,
+ const MCSymbol *Sym = nullptr);
/// Construct a DIE for this abstract scope.
void constructAbstractSubprogramScopeDIE(DwarfCompileUnit &SrcCU, LexicalScope *Scope);
+ /// Construct DIEs for call site entries describing the calls in \p MF.
+ void constructCallSiteEntryDIEs(const DISubprogram &SP, DwarfCompileUnit &CU,
+ DIE &ScopeDIE, const MachineFunction &MF);
+
template <typename DataT>
- void addAccelNameImpl(AccelTable<DataT> &AppleAccel, StringRef Name,
- const DIE &Die);
+ void addAccelNameImpl(const DICompileUnit &CU, AccelTable<DataT> &AppleAccel,
+ StringRef Name, const DIE &Die);
- void finishVariableDefinitions();
+ void finishEntityDefinitions();
void finishSubprogramDefinitions();
@@ -407,9 +492,7 @@ class DwarfDebug : public DebugHandlerBase {
/// Emit address ranges into a debug ranges section.
void emitDebugRanges();
-
- /// Emit range lists into a DWARF v5 debug rnglists section.
- void emitDebugRnglists();
+ void emitDebugRangesDWO();
/// Emit macros into a debug macinfo section.
void emitDebugMacinfo();
@@ -457,6 +540,8 @@ class DwarfDebug : public DebugHandlerBase {
/// Create new DwarfCompileUnit for the given metadata node with tag
/// DW_TAG_compile_unit.
DwarfCompileUnit &getOrCreateDwarfCompileUnit(const DICompileUnit *DIUnit);
+ void finishUnitAttributes(const DICompileUnit *DIUnit,
+ DwarfCompileUnit &NewCU);
/// Construct imported_module or imported_declaration DIE.
void constructAndAddImportedEntityDIE(DwarfCompileUnit &TheCU,
@@ -469,8 +554,8 @@ class DwarfDebug : public DebugHandlerBase {
unsigned Flags);
/// Populate LexicalScope entries with variables' info.
- void collectVariableInfo(DwarfCompileUnit &TheCU, const DISubprogram *SP,
- DenseSet<InlinedVariable> &ProcessedVars);
+ void collectEntityInfo(DwarfCompileUnit &TheCU, const DISubprogram *SP,
+ DenseSet<InlinedEntity> &ProcessedVars);
/// Build the location list for all DBG_VALUEs in the
/// function that describe the same variable.
@@ -479,7 +564,7 @@ class DwarfDebug : public DebugHandlerBase {
/// Collect variable information from the side table maintained by MF.
void collectVariableInfoFromMFTable(DwarfCompileUnit &TheCU,
- DenseSet<InlinedVariable> &P);
+ DenseSet<InlinedEntity> &P);
/// Emit the reference to the section.
void emitSectionReference(const DwarfCompileUnit &CU);
@@ -543,9 +628,6 @@ public:
/// Returns whether to use inline strings.
bool useInlineStrings() const { return UseInlineStrings; }
- /// Returns whether GNU pub sections should be emitted.
- bool usePubSections() const { return UsePubSections; }
-
/// Returns whether ranges section should be emitted.
bool useRangesSection() const { return UseRangesSection; }
@@ -608,17 +690,20 @@ public:
return Ref.resolve();
}
- void addSubprogramNames(const DISubprogram *SP, DIE &Die);
+ void addSubprogramNames(const DICompileUnit &CU, const DISubprogram *SP,
+ DIE &Die);
AddressPool &getAddressPool() { return AddrPool; }
- void addAccelName(StringRef Name, const DIE &Die);
+ void addAccelName(const DICompileUnit &CU, StringRef Name, const DIE &Die);
- void addAccelObjC(StringRef Name, const DIE &Die);
+ void addAccelObjC(const DICompileUnit &CU, StringRef Name, const DIE &Die);
- void addAccelNamespace(StringRef Name, const DIE &Die);
+ void addAccelNamespace(const DICompileUnit &CU, StringRef Name,
+ const DIE &Die);
- void addAccelType(StringRef Name, const DIE &Die, char Flags);
+ void addAccelType(const DICompileUnit &CU, StringRef Name, const DIE &Die,
+ char Flags);
const MachineFunction *getCurrentFunction() const { return CurFn; }
@@ -640,6 +725,9 @@ public:
bool tuneForLLDB() const { return DebuggerTuning == DebuggerKind::LLDB; }
bool tuneForSCE() const { return DebuggerTuning == DebuggerKind::SCE; }
/// @}
+
+ void addSectionLabel(const MCSymbol *Sym);
+ const MCSymbol *getSectionLabel(const MCSection *S);
};
} // end namespace llvm
diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp
index d8d1a5e8f841..19c350afbf17 100644
--- a/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp
+++ b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp
@@ -24,6 +24,20 @@
using namespace llvm;
+void DwarfExpression::emitConstu(uint64_t Value) {
+ if (Value < 32)
+ emitOp(dwarf::DW_OP_lit0 + Value);
+ else if (Value == std::numeric_limits<uint64_t>::max()) {
+ // Only do this for 64-bit values as the DWARF expression stack uses
+ // target-address-size values.
+ emitOp(dwarf::DW_OP_lit0);
+ emitOp(dwarf::DW_OP_not);
+ } else {
+ emitOp(dwarf::DW_OP_constu);
+ emitUnsigned(Value);
+ }
+}
+
void DwarfExpression::addReg(int DwarfReg, const char *Comment) {
assert(DwarfReg >= 0 && "invalid negative dwarf register number");
assert((LocationKind == Unknown || LocationKind == Register) &&
@@ -72,14 +86,12 @@ void DwarfExpression::addOpPiece(unsigned SizeInBits, unsigned OffsetInBits) {
}
void DwarfExpression::addShr(unsigned ShiftBy) {
- emitOp(dwarf::DW_OP_constu);
- emitUnsigned(ShiftBy);
+ emitConstu(ShiftBy);
emitOp(dwarf::DW_OP_shr);
}
void DwarfExpression::addAnd(unsigned Mask) {
- emitOp(dwarf::DW_OP_constu);
- emitUnsigned(Mask);
+ emitConstu(Mask);
emitOp(dwarf::DW_OP_and);
}
@@ -181,8 +193,7 @@ void DwarfExpression::addSignedConstant(int64_t Value) {
void DwarfExpression::addUnsignedConstant(uint64_t Value) {
assert(LocationKind == Implicit || LocationKind == Unknown);
LocationKind = Implicit;
- emitOp(dwarf::DW_OP_constu);
- emitUnsigned(Value);
+ emitConstu(Value);
}
void DwarfExpression::addUnsignedConstant(const APInt &Value) {
@@ -243,10 +254,9 @@ bool DwarfExpression::addMachineRegExpression(const TargetRegisterInfo &TRI,
// Don't emit locations that cannot be expressed without DW_OP_stack_value.
if (DwarfVersion < 4)
- if (std::any_of(ExprCursor.begin(), ExprCursor.end(),
- [](DIExpression::ExprOperand Op) -> bool {
- return Op.getOp() == dwarf::DW_OP_stack_value;
- })) {
+ if (any_of(ExprCursor, [](DIExpression::ExprOperand Op) -> bool {
+ return Op.getOp() == dwarf::DW_OP_stack_value;
+ })) {
DwarfRegs.clear();
LocationKind = Unknown;
return false;
@@ -373,8 +383,7 @@ void DwarfExpression::addExpression(DIExpressionCursor &&ExprCursor,
break;
case dwarf::DW_OP_constu:
assert(LocationKind != Register);
- emitOp(dwarf::DW_OP_constu);
- emitUnsigned(Op->getArg(0));
+ emitConstu(Op->getArg(0));
break;
case dwarf::DW_OP_stack_value:
LocationKind = Implicit;
diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h
index 0637d952eba4..91568ba6d107 100644
--- a/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h
+++ b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.h
@@ -138,6 +138,9 @@ protected:
/// Emit a raw unsigned value.
virtual void emitUnsigned(uint64_t Value) = 0;
+ /// Emit a normalized unsigned constant.
+ void emitConstu(uint64_t Value);
+
/// Return whether the given machine register is the frame register in the
/// current function.
virtual bool isFrameRegister(const TargetRegisterInfo &TRI, unsigned MachineReg) = 0;
@@ -187,7 +190,7 @@ protected:
/// DW_OP_stack_value. Unfortunately, DW_OP_stack_value was not available
/// until DWARF 4, so we will continue to generate DW_OP_constu <const> for
/// DWARF 2 and DWARF 3. Technically, this is incorrect since DW_OP_const
- /// <const> actually describes a value at a constant addess, not a constant
+ /// <const> actually describes a value at a constant address, not a constant
/// value. However, in the past there was no better way to describe a
/// constant value, so the producers and consumers started to rely on
/// heuristics to disambiguate the value vs. location status of the
diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfFile.cpp b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfFile.cpp
index 049f349b009a..78ccad481411 100644
--- a/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfFile.cpp
+++ b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfFile.cpp
@@ -36,13 +36,20 @@ void DwarfFile::emitUnits(bool UseOffsets) {
}
void DwarfFile::emitUnit(DwarfUnit *TheU, bool UseOffsets) {
- DIE &Die = TheU->getUnitDie();
- MCSection *USection = TheU->getSection();
- Asm->OutStreamer->SwitchSection(USection);
+ if (TheU->getCUNode()->isDebugDirectivesOnly())
+ return;
+ MCSection *S = TheU->getSection();
+
+ if (!S)
+ return;
+
+ Asm->OutStreamer->SwitchSection(S);
TheU->emitHeader(UseOffsets);
+ Asm->emitDwarfDIE(TheU->getUnitDie());
- Asm->emitDwarfDIE(Die);
+ if (MCSymbol *EndLabel = TheU->getEndLabel())
+ Asm->OutStreamer->EmitLabel(EndLabel);
}
// Compute the size and offset for each DIE.
@@ -53,6 +60,9 @@ void DwarfFile::computeSizeAndOffsets() {
// Iterate over each compile unit and set the size and offsets for each
// DIE within each compile unit. All offsets are CU relative.
for (const auto &TheU : CUs) {
+ if (TheU->getCUNode()->isDebugDirectivesOnly())
+ continue;
+
TheU->setDebugSectionOffset(SecOffset);
SecOffset += computeSizeAndOffsetsForUnit(TheU.get());
}
@@ -98,3 +108,15 @@ bool DwarfFile::addScopeVariable(LexicalScope *LS, DbgVariable *Var) {
}
return true;
}
+
+void DwarfFile::addScopeLabel(LexicalScope *LS, DbgLabel *Label) {
+ SmallVectorImpl<DbgLabel *> &Labels = ScopeLabels[LS];
+ Labels.push_back(Label);
+}
+
+std::pair<uint32_t, RangeSpanList *>
+DwarfFile::addRange(const DwarfCompileUnit &CU, SmallVector<RangeSpan, 2> R) {
+ CURangeLists.push_back(
+ RangeSpanList(Asm->createTempSymbol("debug_ranges"), CU, std::move(R)));
+ return std::make_pair(CURangeLists.size() - 1, &CURangeLists.back());
+}
diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfFile.h b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfFile.h
index 8dfbc4e1c434..51acca8c1e53 100644
--- a/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfFile.h
+++ b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfFile.h
@@ -24,12 +24,44 @@
namespace llvm {
class AsmPrinter;
+class DbgEntity;
class DbgVariable;
+class DbgLabel;
class DwarfCompileUnit;
class DwarfUnit;
class LexicalScope;
class MCSection;
+// Data structure to hold a range for range lists.
+class RangeSpan {
+public:
+ RangeSpan(MCSymbol *S, MCSymbol *E) : Start(S), End(E) {}
+ const MCSymbol *getStart() const { return Start; }
+ const MCSymbol *getEnd() const { return End; }
+ void setEnd(const MCSymbol *E) { End = E; }
+
+private:
+ const MCSymbol *Start, *End;
+};
+
+class RangeSpanList {
+private:
+ // Index for locating within the debug_range section this particular span.
+ MCSymbol *RangeSym;
+ const DwarfCompileUnit *CU;
+ // List of ranges.
+ SmallVector<RangeSpan, 2> Ranges;
+
+public:
+ RangeSpanList(MCSymbol *Sym, const DwarfCompileUnit &CU,
+ SmallVector<RangeSpan, 2> Ranges)
+ : RangeSym(Sym), CU(&CU), Ranges(std::move(Ranges)) {}
+ 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 {
// Target of Dwarf emission, used for sizing of abbreviations.
AsmPrinter *Asm;
@@ -44,6 +76,10 @@ class DwarfFile {
DwarfStringPool StrPool;
+ // List of range lists for a given compile unit, separate from the ranges for
+ // the CU itself.
+ SmallVector<RangeSpanList, 1> CURangeLists;
+
/// DWARF v5: The symbol that designates the start of the contribution to
/// the string offsets table. The contribution is shared by all units.
MCSymbol *StringOffsetsStartSym = nullptr;
@@ -52,6 +88,10 @@ class DwarfFile {
/// The table is shared by all units.
MCSymbol *RnglistsTableBaseSym = nullptr;
+ /// DWARF v5: The symbol that designates the base of the locations list table.
+ /// The table is shared by all units.
+ MCSymbol *LoclistsTableBaseSym = nullptr;
+
/// The variables of a lexical scope.
struct ScopeVars {
/// We need to sort Args by ArgNo and check for duplicates. This could also
@@ -62,9 +102,13 @@ class DwarfFile {
/// Collection of DbgVariables of each lexical scope.
DenseMap<LexicalScope *, ScopeVars> ScopeVariables;
+ /// Collection of DbgLabels of each lexical scope.
+ using LabelList = SmallVector<DbgLabel *, 4>;
+ DenseMap<LexicalScope *, LabelList> ScopeLabels;
+
// Collection of abstract subprogram DIEs.
DenseMap<const MDNode *, DIE *> AbstractSPDies;
- DenseMap<const MDNode *, std::unique_ptr<DbgVariable>> AbstractVariables;
+ DenseMap<const DINode *, std::unique_ptr<DbgEntity>> AbstractEntities;
/// Maps MDNodes for type system with the corresponding DIEs. These DIEs can
/// be shared across CUs, that is why we keep the map here instead
@@ -78,6 +122,14 @@ public:
return CUs;
}
+ std::pair<uint32_t, RangeSpanList *> addRange(const DwarfCompileUnit &CU,
+ SmallVector<RangeSpan, 2> R);
+
+ /// getRangeLists - Get the vector of range lists.
+ const SmallVectorImpl<RangeSpanList> &getRangeLists() const {
+ return CURangeLists;
+ }
+
/// Compute the size and offset of a DIE given an incoming Offset.
unsigned computeSizeAndOffset(DIE &Die, unsigned Offset);
@@ -112,26 +164,33 @@ public:
DwarfStringPool &getStringPool() { return StrPool; }
MCSymbol *getStringOffsetsStartSym() const { return StringOffsetsStartSym; }
-
void setStringOffsetsStartSym(MCSymbol *Sym) { StringOffsetsStartSym = Sym; }
MCSymbol *getRnglistsTableBaseSym() const { return RnglistsTableBaseSym; }
-
void setRnglistsTableBaseSym(MCSymbol *Sym) { RnglistsTableBaseSym = Sym; }
+ MCSymbol *getLoclistsTableBaseSym() const { return LoclistsTableBaseSym; }
+ void setLoclistsTableBaseSym(MCSymbol *Sym) { LoclistsTableBaseSym = Sym; }
+
/// \returns false if the variable was merged with a previous one.
bool addScopeVariable(LexicalScope *LS, DbgVariable *Var);
+ void addScopeLabel(LexicalScope *LS, DbgLabel *Label);
+
DenseMap<LexicalScope *, ScopeVars> &getScopeVariables() {
return ScopeVariables;
}
+ DenseMap<LexicalScope *, LabelList> &getScopeLabels() {
+ return ScopeLabels;
+ }
+
DenseMap<const MDNode *, DIE *> &getAbstractSPDies() {
return AbstractSPDies;
}
- DenseMap<const MDNode *, std::unique_ptr<DbgVariable>> &getAbstractVariables() {
- return AbstractVariables;
+ DenseMap<const DINode *, std::unique_ptr<DbgEntity>> &getAbstractEntities() {
+ return AbstractEntities;
}
void insertDIE(const MDNode *TypeMD, DIE *Die) {
diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfStringPool.cpp b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfStringPool.cpp
index a61fa83cfb03..02016534a774 100644
--- a/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfStringPool.cpp
+++ b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfStringPool.cpp
@@ -24,25 +24,39 @@ DwarfStringPool::DwarfStringPool(BumpPtrAllocator &A, AsmPrinter &Asm,
: Pool(A), Prefix(Prefix),
ShouldCreateSymbols(Asm.MAI->doesDwarfUseRelocationsAcrossSections()) {}
-DwarfStringPool::EntryRef DwarfStringPool::getEntry(AsmPrinter &Asm,
- StringRef Str) {
+StringMapEntry<DwarfStringPool::EntryTy> &
+DwarfStringPool::getEntryImpl(AsmPrinter &Asm, StringRef Str) {
auto I = Pool.insert(std::make_pair(Str, EntryTy()));
+ auto &Entry = I.first->second;
if (I.second) {
- auto &Entry = I.first->second;
- Entry.Index = Pool.size() - 1;
+ Entry.Index = EntryTy::NotIndexed;
Entry.Offset = NumBytes;
Entry.Symbol = ShouldCreateSymbols ? Asm.createTempSymbol(Prefix) : nullptr;
NumBytes += Str.size() + 1;
assert(NumBytes > Entry.Offset && "Unexpected overflow");
}
- return EntryRef(*I.first);
+ return *I.first;
+}
+
+DwarfStringPool::EntryRef DwarfStringPool::getEntry(AsmPrinter &Asm,
+ StringRef Str) {
+ auto &MapEntry = getEntryImpl(Asm, Str);
+ return EntryRef(MapEntry, false);
+}
+
+DwarfStringPool::EntryRef DwarfStringPool::getIndexedEntry(AsmPrinter &Asm,
+ StringRef Str) {
+ auto &MapEntry = getEntryImpl(Asm, Str);
+ if (!MapEntry.getValue().isIndexed())
+ MapEntry.getValue().Index = NumIndexedStrings++;
+ return EntryRef(MapEntry, true);
}
void DwarfStringPool::emitStringOffsetsTableHeader(AsmPrinter &Asm,
MCSection *Section,
MCSymbol *StartSym) {
- if (empty())
+ if (getNumIndexedStrings() == 0)
return;
Asm.OutStreamer->SwitchSection(Section);
unsigned EntrySize = 4;
@@ -51,7 +65,7 @@ void DwarfStringPool::emitStringOffsetsTableHeader(AsmPrinter &Asm,
// table. The header consists of an entry with the contribution's
// size (not including the size of the length field), the DWARF version and
// 2 bytes of padding.
- Asm.emitInt32(size() * EntrySize + 4);
+ Asm.emitInt32(getNumIndexedStrings() * EntrySize + 4);
Asm.emitInt16(Asm.getDwarfVersion());
Asm.emitInt16(0);
// Define the symbol that marks the start of the contribution. It is
@@ -69,12 +83,17 @@ void DwarfStringPool::emit(AsmPrinter &Asm, MCSection *StrSection,
// Start the dwarf str section.
Asm.OutStreamer->SwitchSection(StrSection);
- // Get all of the string pool entries and put them in an array by their ID so
- // we can sort them.
- SmallVector<const StringMapEntry<EntryTy> *, 64> Entries(Pool.size());
+ // Get all of the string pool entries and sort them by their offset.
+ SmallVector<const StringMapEntry<EntryTy> *, 64> Entries;
+ Entries.reserve(Pool.size());
for (const auto &E : Pool)
- Entries[E.getValue().Index] = &E;
+ Entries.push_back(&E);
+
+ llvm::sort(Entries, [](const StringMapEntry<EntryTy> *A,
+ const StringMapEntry<EntryTy> *B) {
+ return A->getValue().Offset < B->getValue().Offset;
+ });
for (const auto &Entry : Entries) {
assert(ShouldCreateSymbols == static_cast<bool>(Entry->getValue().Symbol) &&
@@ -93,6 +112,14 @@ void DwarfStringPool::emit(AsmPrinter &Asm, MCSection *StrSection,
// If we've got an offset section go ahead and emit that now as well.
if (OffsetSection) {
+ // Now only take the indexed entries and put them in an array by their ID so
+ // we can emit them in order.
+ Entries.resize(NumIndexedStrings);
+ for (const auto &Entry : Pool) {
+ if (Entry.getValue().isIndexed())
+ Entries[Entry.getValue().Index] = &Entry;
+ }
+
Asm.OutStreamer->SwitchSection(OffsetSection);
unsigned size = 4; // FIXME: DWARF64 is 8.
for (const auto &Entry : Entries)
diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfStringPool.h b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfStringPool.h
index 6e6988ea4ad4..f484540d8d37 100644
--- a/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfStringPool.h
+++ b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfStringPool.h
@@ -30,8 +30,11 @@ class DwarfStringPool {
StringMap<EntryTy, BumpPtrAllocator &> Pool;
StringRef Prefix;
unsigned NumBytes = 0;
+ unsigned NumIndexedStrings = 0;
bool ShouldCreateSymbols;
+ StringMapEntry<EntryTy> &getEntryImpl(AsmPrinter &Asm, StringRef Str);
+
public:
using EntryRef = DwarfStringPoolEntryRef;
@@ -48,8 +51,15 @@ public:
unsigned size() const { return Pool.size(); }
+ unsigned getNumIndexedStrings() const { return NumIndexedStrings; }
+
/// Get a reference to an entry in the string pool.
EntryRef getEntry(AsmPrinter &Asm, StringRef Str);
+
+ /// Same as getEntry, except that you can use EntryRef::getIndex to obtain a
+ /// unique ID of this entry (e.g., for use in indexed forms like
+ /// DW_FORM_strx).
+ EntryRef getIndexedEntry(AsmPrinter &Asm, StringRef Str);
};
} // end namespace llvm
diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
index 600f4a78fda0..80b365f1aa43 100644
--- a/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
+++ b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
@@ -234,15 +234,23 @@ void DwarfUnit::addSInt(DIELoc &Die, Optional<dwarf::Form> Form,
void DwarfUnit::addString(DIE &Die, dwarf::Attribute Attribute,
StringRef String) {
+ if (CUNode->isDebugDirectivesOnly())
+ return;
+
if (DD->useInlineStrings()) {
Die.addValue(DIEValueAllocator, Attribute, dwarf::DW_FORM_string,
new (DIEValueAllocator)
DIEInlineString(String, DIEValueAllocator));
return;
}
- auto StringPoolEntry = DU->getStringPool().getEntry(*Asm, String);
dwarf::Form IxForm =
isDwoUnit() ? dwarf::DW_FORM_GNU_str_index : dwarf::DW_FORM_strp;
+
+ auto StringPoolEntry =
+ useSegmentedStringOffsetsTable() || IxForm == dwarf::DW_FORM_GNU_str_index
+ ? DU->getStringPool().getIndexedEntry(*Asm, String)
+ : DU->getStringPool().getEntry(*Asm, String);
+
// For DWARF v5 and beyond, use the smallest strx? form possible.
if (useSegmentedStringOffsetsTable()) {
IxForm = dwarf::DW_FORM_strx1;
@@ -307,14 +315,21 @@ unsigned DwarfTypeUnit::getOrCreateSourceID(const DIFile *File) {
}
void DwarfUnit::addOpAddress(DIELoc &Die, const MCSymbol *Sym) {
- if (!DD->useSplitDwarf()) {
- addUInt(Die, dwarf::DW_FORM_data1, dwarf::DW_OP_addr);
- addLabel(Die, dwarf::DW_FORM_udata, Sym);
- } else {
+ if (DD->getDwarfVersion() >= 5) {
+ addUInt(Die, dwarf::DW_FORM_data1, dwarf::DW_OP_addrx);
+ addUInt(Die, dwarf::DW_FORM_addrx, DD->getAddressPool().getIndex(Sym));
+ return;
+ }
+
+ if (DD->useSplitDwarf()) {
addUInt(Die, dwarf::DW_FORM_data1, dwarf::DW_OP_GNU_addr_index);
addUInt(Die, dwarf::DW_FORM_GNU_addr_index,
DD->getAddressPool().getIndex(Sym));
+ return;
}
+
+ addUInt(Die, dwarf::DW_FORM_data1, dwarf::DW_OP_addr);
+ addLabel(Die, dwarf::DW_FORM_udata, Sym);
}
void DwarfUnit::addLabelDelta(DIE &Die, dwarf::Attribute Attribute,
@@ -401,6 +416,12 @@ void DwarfUnit::addSourceLine(DIE &Die, const DISubprogram *SP) {
addSourceLine(Die, SP->getLine(), SP->getFile());
}
+void DwarfUnit::addSourceLine(DIE &Die, const DILabel *L) {
+ assert(L);
+
+ addSourceLine(Die, L->getLine(), L->getFile());
+}
+
void DwarfUnit::addSourceLine(DIE &Die, const DIType *Ty) {
assert(Ty);
@@ -413,138 +434,6 @@ void DwarfUnit::addSourceLine(DIE &Die, const DIObjCProperty *Ty) {
addSourceLine(Die, Ty->getLine(), Ty->getFile());
}
-/* Byref variables, in Blocks, are declared by the programmer as "SomeType
- VarName;", but the compiler creates a __Block_byref_x_VarName struct, and
- gives the variable VarName either the struct, or a pointer to the struct, as
- its type. This is necessary for various behind-the-scenes things the
- compiler needs to do with by-reference variables in Blocks.
-
- However, as far as the original *programmer* is concerned, the variable
- should still have type 'SomeType', as originally declared.
-
- The function getBlockByrefType dives into the __Block_byref_x_VarName
- struct to find the original type of the variable, which is then assigned to
- the variable's Debug Information Entry as its real type. So far, so good.
- However now the debugger will expect the variable VarName to have the type
- SomeType. So we need the location attribute for the variable to be an
- expression that explains to the debugger how to navigate through the
- pointers and struct to find the actual variable of type SomeType.
-
- The following function does just that. We start by getting
- the "normal" location for the variable. This will be the location
- of either the struct __Block_byref_x_VarName or the pointer to the
- struct __Block_byref_x_VarName.
-
- The struct will look something like:
-
- struct __Block_byref_x_VarName {
- ... <various fields>
- struct __Block_byref_x_VarName *forwarding;
- ... <various other fields>
- SomeType VarName;
- ... <maybe more fields>
- };
-
- If we are given the struct directly (as our starting point) we
- need to tell the debugger to:
-
- 1). Add the offset of the forwarding field.
-
- 2). Follow that pointer to get the real __Block_byref_x_VarName
- struct to use (the real one may have been copied onto the heap).
-
- 3). Add the offset for the field VarName, to find the actual variable.
-
- If we started with a pointer to the struct, then we need to
- dereference that pointer first, before the other steps.
- Translating this into DWARF ops, we will need to append the following
- to the current location description for the variable:
-
- DW_OP_deref -- optional, if we start with a pointer
- DW_OP_plus_uconst <forward_fld_offset>
- DW_OP_deref
- DW_OP_plus_uconst <varName_fld_offset>
-
- That is what this function does. */
-
-void DwarfUnit::addBlockByrefAddress(const DbgVariable &DV, DIE &Die,
- dwarf::Attribute Attribute,
- const MachineLocation &Location) {
- const DIType *Ty = DV.getType();
- const DIType *TmpTy = Ty;
- uint16_t Tag = Ty->getTag();
- bool isPointer = false;
-
- StringRef varName = DV.getName();
-
- if (Tag == dwarf::DW_TAG_pointer_type) {
- auto *DTy = cast<DIDerivedType>(Ty);
- TmpTy = resolve(DTy->getBaseType());
- isPointer = true;
- }
-
- // Find the __forwarding field and the variable field in the __Block_byref
- // struct.
- DINodeArray Fields = cast<DICompositeType>(TmpTy)->getElements();
- const DIDerivedType *varField = nullptr;
- const DIDerivedType *forwardingField = nullptr;
-
- for (unsigned i = 0, N = Fields.size(); i < N; ++i) {
- auto *DT = cast<DIDerivedType>(Fields[i]);
- StringRef fieldName = DT->getName();
- if (fieldName == "__forwarding")
- forwardingField = DT;
- else if (fieldName == varName)
- varField = DT;
- }
-
- // Get the offsets for the forwarding field and the variable field.
- unsigned forwardingFieldOffset = forwardingField->getOffsetInBits() >> 3;
- unsigned varFieldOffset = varField->getOffsetInBits() >> 2;
-
- // Decode the original location, and use that as the start of the byref
- // variable's location.
- DIELoc *Loc = new (DIEValueAllocator) DIELoc;
- DIEDwarfExpression DwarfExpr(*Asm, *this, *Loc);
- if (Location.isIndirect())
- DwarfExpr.setMemoryLocationKind();
-
- SmallVector<uint64_t, 6> Ops;
- // If we started with a pointer to the __Block_byref... struct, then
- // the first thing we need to do is dereference the pointer (DW_OP_deref).
- if (isPointer)
- Ops.push_back(dwarf::DW_OP_deref);
-
- // Next add the offset for the '__forwarding' field:
- // DW_OP_plus_uconst ForwardingFieldOffset. Note there's no point in
- // adding the offset if it's 0.
- if (forwardingFieldOffset > 0) {
- Ops.push_back(dwarf::DW_OP_plus_uconst);
- Ops.push_back(forwardingFieldOffset);
- }
-
- // Now dereference the __forwarding field to get to the real __Block_byref
- // struct: DW_OP_deref.
- Ops.push_back(dwarf::DW_OP_deref);
-
- // Now that we've got the real __Block_byref... struct, add the offset
- // for the variable's field to get to the location of the actual variable:
- // DW_OP_plus_uconst varFieldOffset. Again, don't add if it's 0.
- if (varFieldOffset > 0) {
- Ops.push_back(dwarf::DW_OP_plus_uconst);
- Ops.push_back(varFieldOffset);
- }
-
- DIExpressionCursor Cursor(Ops);
- const TargetRegisterInfo &TRI = *Asm->MF->getSubtarget().getRegisterInfo();
- if (!DwarfExpr.addMachineRegExpression(TRI, Cursor, Location.getReg()))
- return;
- DwarfExpr.addExpression(std::move(Cursor));
-
- // Now attach the location information to the DIE.
- addBlock(Die, Attribute, DwarfExpr.finalize());
-}
-
/// Return true if type encoding is unsigned.
static bool isUnsignedDIType(DwarfDebug *DD, const DIType *Ty) {
if (auto *CTy = dyn_cast<DICompositeType>(Ty)) {
@@ -787,7 +676,7 @@ void DwarfUnit::updateAcceleratorTables(const DIScope *Context,
IsImplementation = CT->getRuntimeLang() == 0 || CT->isObjcClassComplete();
}
unsigned Flags = IsImplementation ? dwarf::DW_FLAG_type_implementation : 0;
- DD->addAccelType(Ty->getName(), TyDIE, Flags);
+ DD->addAccelType(*CUNode, Ty->getName(), TyDIE, Flags);
if (!Context || isa<DICompileUnit>(Context) || isa<DIFile>(Context) ||
isa<DINamespace>(Context))
@@ -851,6 +740,11 @@ void DwarfUnit::constructTypeDIE(DIE &Buffer, const DIBasicType *BTy) {
uint64_t Size = BTy->getSizeInBits() >> 3;
addUInt(Buffer, dwarf::DW_AT_byte_size, None, Size);
+
+ if (BTy->isBigEndian())
+ addUInt(Buffer, dwarf::DW_AT_endianity, None, dwarf::DW_END_big);
+ else if (BTy->isLittleEndian())
+ addUInt(Buffer, dwarf::DW_AT_endianity, None, dwarf::DW_END_little);
}
void DwarfUnit::constructTypeDIE(DIE &Buffer, const DIDerivedType *DTy) {
@@ -1155,7 +1049,7 @@ DIE *DwarfUnit::getOrCreateNameSpace(const DINamespace *NS) {
addString(NDie, dwarf::DW_AT_name, NS->getName());
else
Name = "(anonymous namespace)";
- DD->addAccelNamespace(Name, NDie);
+ DD->addAccelNamespace(*CUNode, Name, NDie);
addGlobalName(Name, NDie, NS->getScope());
if (NS->getExportSymbols())
addFlag(NDie, dwarf::DW_AT_export_symbols);
@@ -1404,7 +1298,7 @@ DIE *DwarfUnit::getIndexTyDie() {
addUInt(*IndexTyDie, dwarf::DW_AT_byte_size, None, sizeof(int64_t));
addUInt(*IndexTyDie, dwarf::DW_AT_encoding, dwarf::DW_FORM_data1,
dwarf::DW_ATE_unsigned);
- DD->addAccelType(Name, *IndexTyDie, /*Flags*/ 0);
+ DD->addAccelType(*CUNode, Name, *IndexTyDie, /*Flags*/ 0);
return IndexTyDie;
}
@@ -1467,7 +1361,7 @@ void DwarfUnit::constructEnumTypeDIE(DIE &Buffer, const DICompositeType *CTy) {
if (DTy) {
if (DD->getDwarfVersion() >= 3)
addType(Buffer, DTy);
- if (DD->getDwarfVersion() >= 4 && (CTy->getFlags() & DINode::FlagFixedEnum))
+ if (DD->getDwarfVersion() >= 4 && (CTy->getFlags() & DINode::FlagEnumClass))
addFlag(Buffer, dwarf::DW_AT_enum_class);
}
@@ -1659,7 +1553,14 @@ DIE *DwarfUnit::getOrCreateStaticMemberDIE(const DIDerivedType *DT) {
void DwarfUnit::emitCommonHeader(bool UseOffsets, dwarf::UnitType UT) {
// Emit size of content not including length itself
Asm->OutStreamer->AddComment("Length of Unit");
- Asm->emitInt32(getHeaderSize() + getUnitDie().getSize());
+ if (!DD->useSectionsAsReferences()) {
+ StringRef Prefix = isDwoUnit() ? "debug_info_dwo_" : "debug_info_";
+ MCSymbol *BeginLabel = Asm->createTempSymbol(Prefix + "start");
+ EndLabel = Asm->createTempSymbol(Prefix + "end");
+ Asm->EmitLabelDifference(EndLabel, BeginLabel, 4);
+ Asm->OutStreamer->EmitLabel(BeginLabel);
+ } else
+ Asm->emitInt32(getHeaderSize() + getUnitDie().getSize());
Asm->OutStreamer->AddComment("DWARF version number");
unsigned Version = DD->getDwarfVersion();
@@ -1761,3 +1662,12 @@ void DwarfUnit::addRnglistsBase() {
DU->getRnglistsTableBaseSym(),
TLOF.getDwarfRnglistsSection()->getBeginSymbol());
}
+
+void DwarfUnit::addLoclistsBase() {
+ assert(DD->getDwarfVersion() >= 5 &&
+ "DW_AT_loclists_base requires DWARF version 5 or later");
+ const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering();
+ addSectionLabel(getUnitDie(), dwarf::DW_AT_loclists_base,
+ DU->getLoclistsTableBaseSym(),
+ TLOF.getDwarfLoclistsSection()->getBeginSymbol());
+}
diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h
index 69696f626536..a59ebb7c1465 100644
--- a/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h
+++ b/contrib/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h
@@ -35,33 +35,6 @@ class ConstantFP;
class DbgVariable;
class DwarfCompileUnit;
-// Data structure to hold a range for range lists.
-class RangeSpan {
-public:
- RangeSpan(MCSymbol *S, MCSymbol *E) : Start(S), End(E) {}
- const MCSymbol *getStart() const { return Start; }
- const MCSymbol *getEnd() const { return End; }
- void setEnd(const MCSymbol *E) { End = E; }
-
-private:
- const MCSymbol *Start, *End;
-};
-
-class RangeSpanList {
-private:
- // Index for locating within the debug_range section this particular span.
- MCSymbol *RangeSym;
- // List of ranges.
- SmallVector<RangeSpan, 2> Ranges;
-
-public:
- RangeSpanList(MCSymbol *Sym, SmallVector<RangeSpan, 2> Ranges)
- : RangeSym(Sym), Ranges(std::move(Ranges)) {}
- MCSymbol *getSym() const { return RangeSym; }
- const SmallVectorImpl<RangeSpan> &getRanges() const { return Ranges; }
- void addRange(RangeSpan Range) { Ranges.push_back(Range); }
-};
-
//===----------------------------------------------------------------------===//
/// This dwarf writer support class manages information associated with a
/// source file.
@@ -76,6 +49,9 @@ protected:
/// Target of Dwarf emission.
AsmPrinter *Asm;
+ /// Emitted at the end of the CU and used to compute the CU Length field.
+ MCSymbol *EndLabel = nullptr;
+
// Holders for some common dwarf information.
DwarfDebug *DD;
DwarfFile *DU;
@@ -109,6 +85,7 @@ protected:
public:
// Accessors.
AsmPrinter* getAsmPrinter() const { return Asm; }
+ MCSymbol *getEndLabel() const { return EndLabel; }
uint16_t getLanguage() const { return CUNode->getSourceLanguage(); }
const DICompileUnit *getCUNode() const { return CUNode; }
@@ -213,6 +190,7 @@ public:
void addSourceLine(DIE &Die, const DILocalVariable *V);
void addSourceLine(DIE &Die, const DIGlobalVariable *G);
void addSourceLine(DIE &Die, const DISubprogram *SP);
+ void addSourceLine(DIE &Die, const DILabel *L);
void addSourceLine(DIE &Die, const DIType *Ty);
void addSourceLine(DIE &Die, const DIObjCProperty *Ty);
@@ -298,6 +276,9 @@ public:
/// Add the DW_AT_rnglists_base attribute to the unit DIE.
void addRnglistsBase();
+ /// Add the DW_AT_loclists_base attribute to the unit DIE.
+ void addLoclistsBase();
+
virtual DwarfCompileUnit &getCU() = 0;
void constructTypeDIE(DIE &Buffer, const DICompositeType *CTy);
diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/EHStreamer.cpp b/contrib/llvm/lib/CodeGen/AsmPrinter/EHStreamer.cpp
index 65de9d7e65a4..7599121de2b0 100644
--- a/contrib/llvm/lib/CodeGen/AsmPrinter/EHStreamer.cpp
+++ b/contrib/llvm/lib/CodeGen/AsmPrinter/EHStreamer.cpp
@@ -99,7 +99,7 @@ void EHStreamer::computeActionsTable(
FirstActions.reserve(LandingPads.size());
int FirstAction = 0;
- unsigned SizeActions = 0;
+ unsigned SizeActions = 0; // Total size of all action entries for a function
const LandingPadInfo *PrevLPI = nullptr;
for (SmallVectorImpl<const LandingPadInfo *>::const_iterator
@@ -107,23 +107,24 @@ void EHStreamer::computeActionsTable(
const LandingPadInfo *LPI = *I;
const std::vector<int> &TypeIds = LPI->TypeIds;
unsigned NumShared = PrevLPI ? sharedTypeIDs(LPI, PrevLPI) : 0;
- unsigned SizeSiteActions = 0;
+ unsigned SizeSiteActions = 0; // Total size of all entries for a landingpad
if (NumShared < TypeIds.size()) {
- unsigned SizeAction = 0;
+ // Size of one action entry (typeid + next action)
+ unsigned SizeActionEntry = 0;
unsigned PrevAction = (unsigned)-1;
if (NumShared) {
unsigned SizePrevIds = PrevLPI->TypeIds.size();
assert(Actions.size());
PrevAction = Actions.size() - 1;
- SizeAction = getSLEB128Size(Actions[PrevAction].NextAction) +
- getSLEB128Size(Actions[PrevAction].ValueForTypeID);
+ SizeActionEntry = getSLEB128Size(Actions[PrevAction].NextAction) +
+ getSLEB128Size(Actions[PrevAction].ValueForTypeID);
for (unsigned j = NumShared; j != SizePrevIds; ++j) {
assert(PrevAction != (unsigned)-1 && "PrevAction is invalid!");
- SizeAction -= getSLEB128Size(Actions[PrevAction].ValueForTypeID);
- SizeAction += -Actions[PrevAction].NextAction;
+ SizeActionEntry -= getSLEB128Size(Actions[PrevAction].ValueForTypeID);
+ SizeActionEntry += -Actions[PrevAction].NextAction;
PrevAction = Actions[PrevAction].Previous;
}
}
@@ -136,9 +137,9 @@ void EHStreamer::computeActionsTable(
isFilterEHSelector(TypeID) ? FilterOffsets[-1 - TypeID] : TypeID;
unsigned SizeTypeID = getSLEB128Size(ValueForTypeID);
- int NextAction = SizeAction ? -(SizeAction + SizeTypeID) : 0;
- SizeAction = SizeTypeID + getSLEB128Size(NextAction);
- SizeSiteActions += SizeAction;
+ int NextAction = SizeActionEntry ? -(SizeActionEntry + SizeTypeID) : 0;
+ SizeActionEntry = SizeTypeID + getSLEB128Size(NextAction);
+ SizeSiteActions += SizeActionEntry;
ActionEntry Action = { ValueForTypeID, NextAction, PrevAction };
Actions.push_back(Action);
@@ -146,7 +147,7 @@ void EHStreamer::computeActionsTable(
}
// Record the first action of the landing pad site.
- FirstAction = SizeActions + SizeSiteActions - SizeAction + 1;
+ FirstAction = SizeActions + SizeSiteActions - SizeActionEntry + 1;
} // else identical - re-use previous FirstAction
// Information used when creating the call-site table. The action record
@@ -344,7 +345,9 @@ computeCallSiteTable(SmallVectorImpl<CallSiteEntry> &CallSites,
/// unwound and handling continues.
/// 3. Type ID table contains references to all the C++ typeinfo for all
/// catches in the function. This tables is reverse indexed base 1.
-void EHStreamer::emitExceptionTable() {
+///
+/// Returns the starting symbol of an exception table.
+MCSymbol *EHStreamer::emitExceptionTable() {
const MachineFunction *MF = Asm->MF;
const std::vector<const GlobalValue *> &TypeInfos = MF->getTypeInfos();
const std::vector<unsigned> &FilterIds = MF->getFilterIds();
@@ -359,9 +362,9 @@ void EHStreamer::emitExceptionTable() {
LandingPads.push_back(&PadInfos[i]);
// Order landing pads lexicographically by type id.
- llvm::sort(LandingPads.begin(), LandingPads.end(),
- [](const LandingPadInfo *L,
- const LandingPadInfo *R) { return L->TypeIds < R->TypeIds; });
+ llvm::sort(LandingPads, [](const LandingPadInfo *L, const LandingPadInfo *R) {
+ return L->TypeIds < R->TypeIds;
+ });
// Compute the actions table and gather the first action index for each
// landing pad site.
@@ -374,6 +377,7 @@ void EHStreamer::emitExceptionTable() {
computeCallSiteTable(CallSites, LandingPads, FirstActions);
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;
bool HaveTTData = !TypeInfos.empty() || !FilterIds.empty();
@@ -456,8 +460,8 @@ void EHStreamer::emitExceptionTable() {
Asm->EmitLabelDifferenceAsULEB128(CstEndLabel, CstBeginLabel);
Asm->OutStreamer->EmitLabel(CstBeginLabel);
- // SjLj Exception handling
- if (IsSJLJ) {
+ // SjLj / Wasm Exception handling
+ if (IsSJLJ || IsWasm) {
unsigned idx = 0;
for (SmallVectorImpl<CallSiteEntry>::const_iterator
I = CallSites.begin(), E = CallSites.end(); I != E; ++I, ++idx) {
@@ -603,6 +607,7 @@ void EHStreamer::emitExceptionTable() {
}
Asm->EmitAlignment(2);
+ return GCCETSym;
}
void EHStreamer::emitTypeInfos(unsigned TTypeEncoding, MCSymbol *TTBaseLabel) {
diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/EHStreamer.h b/contrib/llvm/lib/CodeGen/AsmPrinter/EHStreamer.h
index b89421a1e067..ce912d032c6d 100644
--- a/contrib/llvm/lib/CodeGen/AsmPrinter/EHStreamer.h
+++ b/contrib/llvm/lib/CodeGen/AsmPrinter/EHStreamer.h
@@ -14,8 +14,8 @@
#ifndef LLVM_LIB_CODEGEN_ASMPRINTER_EHSTREAMER_H
#define LLVM_LIB_CODEGEN_ASMPRINTER_EHSTREAMER_H
-#include "AsmPrinterHandler.h"
#include "llvm/ADT/DenseMap.h"
+#include "llvm/CodeGen/AsmPrinterHandler.h"
#include "llvm/Support/Compiler.h"
namespace llvm {
@@ -85,9 +85,10 @@ protected:
/// zero for the landing pad and the action. Calls marked 'nounwind' have
/// no entry and must not be contained in the try-range of any entry - they
/// form gaps in the table. Entries must be ordered by try-range address.
- void computeCallSiteTable(SmallVectorImpl<CallSiteEntry> &CallSites,
- const SmallVectorImpl<const LandingPadInfo *> &LandingPads,
- const SmallVectorImpl<unsigned> &FirstActions);
+ virtual void computeCallSiteTable(
+ SmallVectorImpl<CallSiteEntry> &CallSites,
+ const SmallVectorImpl<const LandingPadInfo *> &LandingPads,
+ const SmallVectorImpl<unsigned> &FirstActions);
/// Emit landing pads and actions.
///
@@ -108,7 +109,9 @@ protected:
/// found the frame is unwound and handling continues.
/// 3. Type id table contains references to all the C++ typeinfo for all
/// catches in the function. This tables is reversed indexed base 1.
- void emitExceptionTable();
+ ///
+ /// Returns the starting symbol of an exception table.
+ MCSymbol *emitExceptionTable();
virtual void emitTypeInfos(unsigned TTypeEncoding, MCSymbol *TTBaseLabel);
diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/ErlangGCPrinter.cpp b/contrib/llvm/lib/CodeGen/AsmPrinter/ErlangGCPrinter.cpp
index 49cc376fcc98..34677ecc9e69 100644
--- a/contrib/llvm/lib/CodeGen/AsmPrinter/ErlangGCPrinter.cpp
+++ b/contrib/llvm/lib/CodeGen/AsmPrinter/ErlangGCPrinter.cpp
@@ -15,10 +15,10 @@
#include "llvm/BinaryFormat/ELF.h"
#include "llvm/CodeGen/AsmPrinter.h"
+#include "llvm/CodeGen/BuiltinGCs.h"
#include "llvm/CodeGen/GCMetadata.h"
#include "llvm/CodeGen/GCMetadataPrinter.h"
#include "llvm/CodeGen/GCStrategy.h"
-#include "llvm/CodeGen/GCs.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Module.h"
diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/OcamlGCPrinter.cpp b/contrib/llvm/lib/CodeGen/AsmPrinter/OcamlGCPrinter.cpp
index 59a57ed30d10..3479a00def23 100644
--- a/contrib/llvm/lib/CodeGen/AsmPrinter/OcamlGCPrinter.cpp
+++ b/contrib/llvm/lib/CodeGen/AsmPrinter/OcamlGCPrinter.cpp
@@ -15,9 +15,9 @@
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/Twine.h"
#include "llvm/CodeGen/AsmPrinter.h"
+#include "llvm/CodeGen/BuiltinGCs.h"
#include "llvm/CodeGen/GCMetadata.h"
#include "llvm/CodeGen/GCMetadataPrinter.h"
-#include "llvm/CodeGen/GCs.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Mangler.h"
diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/WasmException.cpp b/contrib/llvm/lib/CodeGen/AsmPrinter/WasmException.cpp
new file mode 100644
index 000000000000..527e5ae50146
--- /dev/null
+++ b/contrib/llvm/lib/CodeGen/AsmPrinter/WasmException.cpp
@@ -0,0 +1,97 @@
+//===-- 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.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains support for writing WebAssembly exception info into asm
+// files.
+//
+//===----------------------------------------------------------------------===//
+
+#include "WasmException.h"
+#include "llvm/IR/Mangler.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCStreamer.h"
+using namespace llvm;
+
+void WasmException::endModule() {
+ // This is the symbol used in 'throw' and 'if_except' 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
+ // symbol only if so.
+ SmallString<60> NameStr;
+ Mangler::getNameWithPrefix(NameStr, "__cpp_exception", Asm->getDataLayout());
+ if (Asm->OutContext.lookupSymbol(NameStr)) {
+ MCSymbol *ExceptionSym = Asm->GetExternalSymbolSymbol("__cpp_exception");
+ Asm->OutStreamer->EmitLabel(ExceptionSym);
+ }
+}
+
+void WasmException::markFunctionEnd() {
+ // Get rid of any dead landing pads.
+ if (!Asm->MF->getLandingPads().empty()) {
+ auto *NonConstMF = const_cast<MachineFunction *>(Asm->MF);
+ // Wasm does not set BeginLabel and EndLabel information for landing pads,
+ // so we should set the second argument false.
+ NonConstMF->tidyLandingPads(nullptr, /* TidyIfNoBeginLabels */ false);
+ }
+}
+
+void WasmException::endFunction(const MachineFunction *MF) {
+ bool ShouldEmitExceptionTable = false;
+ for (const LandingPadInfo &Info : MF->getLandingPads()) {
+ if (MF->hasWasmLandingPadIndex(Info.LandingPadBlock)) {
+ ShouldEmitExceptionTable = true;
+ break;
+ }
+ }
+ if (!ShouldEmitExceptionTable)
+ return;
+ MCSymbol *LSDALabel = emitExceptionTable();
+ assert(LSDALabel && ".GCC_exception_table has not been emitted!");
+
+ // Wasm requires every data section symbol to have a .size set. So we emit an
+ // end marker and set the size as the difference between the start end the end
+ // marker.
+ MCSymbol *LSDAEndLabel = Asm->createTempSymbol("GCC_except_table_end");
+ Asm->OutStreamer->EmitLabel(LSDAEndLabel);
+ MCContext &OutContext = Asm->OutStreamer->getContext();
+ const MCExpr *SizeExp = MCBinaryExpr::createSub(
+ MCSymbolRefExpr::create(LSDAEndLabel, OutContext),
+ MCSymbolRefExpr::create(LSDALabel, OutContext), OutContext);
+ Asm->OutStreamer->emitELFSize(LSDALabel, SizeExp);
+}
+
+// Compute the call-site table for wasm EH. Even though we use the same function
+// name to share the common routines, a call site entry in the table corresponds
+// to not a call site for possibly-throwing functions but a landing pad. In wasm
+// EH the VM is responsible for stack unwinding. After an exception occurs and
+// the stack is unwound, the control flow is transferred to wasm 'catch'
+// instruction by the VM, after which the personality function is called from
+// the compiler-generated code. Refer to WasmEHPrepare pass for more
+// information.
+void WasmException::computeCallSiteTable(
+ SmallVectorImpl<CallSiteEntry> &CallSites,
+ const SmallVectorImpl<const LandingPadInfo *> &LandingPads,
+ const SmallVectorImpl<unsigned> &FirstActions) {
+ MachineFunction &MF = *Asm->MF;
+ for (unsigned I = 0, N = LandingPads.size(); I < N; ++I) {
+ const LandingPadInfo *Info = LandingPads[I];
+ MachineBasicBlock *LPad = Info->LandingPadBlock;
+ // We don't emit LSDA for single catch (...).
+ if (!MF.hasWasmLandingPadIndex(LPad))
+ continue;
+ // Wasm EH must maintain the EH pads in the order assigned to them by the
+ // WasmEHPrepare pass.
+ unsigned LPadIndex = MF.getWasmLandingPadIndex(LPad);
+ CallSiteEntry Site = {nullptr, nullptr, Info, FirstActions[I]};
+ if (CallSites.size() < LPadIndex + 1)
+ CallSites.resize(LPadIndex + 1);
+ CallSites[LPadIndex] = Site;
+ }
+}
diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/WasmException.h b/contrib/llvm/lib/CodeGen/AsmPrinter/WasmException.h
new file mode 100644
index 000000000000..cbdb42457cf8
--- /dev/null
+++ b/contrib/llvm/lib/CodeGen/AsmPrinter/WasmException.h
@@ -0,0 +1,42 @@
+//===-- 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.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains support for writing WebAssembly exception info into asm
+// files.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_CODEGEN_ASMPRINTER_WASMEXCEPTION_H
+#define LLVM_LIB_CODEGEN_ASMPRINTER_WASMEXCEPTION_H
+
+#include "EHStreamer.h"
+#include "llvm/CodeGen/AsmPrinter.h"
+
+namespace llvm {
+
+class LLVM_LIBRARY_VISIBILITY WasmException : public EHStreamer {
+public:
+ WasmException(AsmPrinter *A) : EHStreamer(A) {}
+
+ void endModule() override;
+ void beginFunction(const MachineFunction *MF) override {}
+ virtual void markFunctionEnd() override;
+ void endFunction(const MachineFunction *MF) override;
+
+protected:
+ // Compute the call site table for wasm EH.
+ void computeCallSiteTable(
+ SmallVectorImpl<CallSiteEntry> &CallSites,
+ const SmallVectorImpl<const LandingPadInfo *> &LandingPads,
+ const SmallVectorImpl<unsigned> &FirstActions) override;
+};
+
+} // End of namespace llvm
+
+#endif
diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/WinCFGuard.h b/contrib/llvm/lib/CodeGen/AsmPrinter/WinCFGuard.h
index 124e8f04bfad..28f119e35966 100644
--- a/contrib/llvm/lib/CodeGen/AsmPrinter/WinCFGuard.h
+++ b/contrib/llvm/lib/CodeGen/AsmPrinter/WinCFGuard.h
@@ -14,7 +14,7 @@
#ifndef LLVM_LIB_CODEGEN_ASMPRINTER_WINCFGUARD_H
#define LLVM_LIB_CODEGEN_ASMPRINTER_WINCFGUARD_H
-#include "AsmPrinterHandler.h"
+#include "llvm/CodeGen/AsmPrinterHandler.h"
#include "llvm/Support/Compiler.h"
namespace llvm {
diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/WinException.cpp b/contrib/llvm/lib/CodeGen/AsmPrinter/WinException.cpp
index eff73a58d8d2..cf8e8c69bc2a 100644
--- a/contrib/llvm/lib/CodeGen/AsmPrinter/WinException.cpp
+++ b/contrib/llvm/lib/CodeGen/AsmPrinter/WinException.cpp
@@ -42,6 +42,7 @@ WinException::WinException(AsmPrinter *A) : EHStreamer(A) {
// MSVC's EH tables are always composed of 32-bit words. All known 64-bit
// platforms use an imagerel32 relocation to refer to symbols.
useImageRel32 = (A->getDataLayout().getPointerSizeInBits() == 64);
+ isAArch64 = Asm->TM.getTargetTriple().isAArch64();
}
WinException::~WinException() {}
@@ -242,6 +243,17 @@ void WinException::endFunclet() {
if (F.hasPersonalityFn())
Per = classifyEHPersonality(F.getPersonalityFn()->stripPointerCasts());
+ // On funclet exit, we emit a fake "function" end marker, so that the call
+ // 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);
+ }
+
// Emit an UNWIND_INFO struct describing the prologue.
Asm->OutStreamer->EmitWinEHHandlerData();
@@ -286,7 +298,10 @@ const MCExpr *WinException::create32bitRef(const GlobalValue *GV) {
return create32bitRef(Asm->getSymbol(GV));
}
-const MCExpr *WinException::getLabelPlusOne(const MCSymbol *Label) {
+const MCExpr *WinException::getLabel(const MCSymbol *Label) {
+ if (isAArch64)
+ return MCSymbolRefExpr::create(Label, MCSymbolRefExpr::VK_COFF_IMGREL32,
+ Asm->OutContext);
return MCBinaryExpr::createAdd(create32bitRef(Label),
MCConstantExpr::create(1, Asm->OutContext),
Asm->OutContext);
@@ -531,7 +546,7 @@ void WinException::emitCSpecificHandlerTable(const MachineFunction *MF) {
};
// Emit a label assignment with the SEH frame offset so we can use it for
- // llvm.x86.seh.recoverfp.
+ // llvm.eh.recoverfp.
StringRef FLinkageName =
GlobalValue::dropLLVMManglingEscape(MF->getFunction().getName());
MCSymbol *ParentFrameOffset =
@@ -588,7 +603,6 @@ void WinException::emitSEHActionsForRange(const WinEHFuncInfo &FuncInfo,
const MCSymbol *EndLabel, int State) {
auto &OS = *Asm->OutStreamer;
MCContext &Ctx = Asm->OutContext;
-
bool VerboseAsm = OS.isVerboseAsm();
auto AddComment = [&](const Twine &Comment) {
if (VerboseAsm)
@@ -613,9 +627,9 @@ void WinException::emitSEHActionsForRange(const WinEHFuncInfo &FuncInfo,
}
AddComment("LabelStart");
- OS.EmitValue(getLabelPlusOne(BeginLabel), 4);
+ OS.EmitValue(getLabel(BeginLabel), 4);
AddComment("LabelEnd");
- OS.EmitValue(getLabelPlusOne(EndLabel), 4);
+ OS.EmitValue(getLabel(EndLabel), 4);
AddComment(UME.IsFinally ? "FinallyFunclet" : UME.Filter ? "FilterFunction"
: "CatchAll");
OS.EmitValue(FilterOrFinally, 4);
@@ -799,7 +813,7 @@ void WinException::emitCXXFrameHandler3Table(const MachineFunction *MF) {
// TypeDescriptor *Type;
// int32_t CatchObjOffset;
// void (*Handler)();
- // int32_t ParentFrameOffset; // x64 only
+ // int32_t ParentFrameOffset; // x64 and AArch64 only
// };
OS.EmitLabel(HandlerMapXData);
for (const WinEHHandlerType &HT : TBME.HandlerArray) {
@@ -901,7 +915,7 @@ void WinException::computeIP2StateTable(
ChangeLabel = StateChange.PreviousEndLabel;
// Emit an entry indicating that PCs after 'Label' have this EH state.
IPToStateTable.push_back(
- std::make_pair(getLabelPlusOne(ChangeLabel), StateChange.NewState));
+ std::make_pair(getLabel(ChangeLabel), StateChange.NewState));
// FIXME: assert that NewState is between CatchLow and CatchHigh.
}
}
diff --git a/contrib/llvm/lib/CodeGen/AsmPrinter/WinException.h b/contrib/llvm/lib/CodeGen/AsmPrinter/WinException.h
index eed3c4453ffc..37c796f89765 100644
--- a/contrib/llvm/lib/CodeGen/AsmPrinter/WinException.h
+++ b/contrib/llvm/lib/CodeGen/AsmPrinter/WinException.h
@@ -38,6 +38,9 @@ class LLVM_LIBRARY_VISIBILITY WinException : public EHStreamer {
/// True if this is a 64-bit target and we should use image relative offsets.
bool useImageRel32 = false;
+ /// True if we are generating exception handling on Windows for ARM64.
+ bool isAArch64 = false;
+
/// Pointer to the current funclet entry BB.
const MachineBasicBlock *CurrentFuncletEntry = nullptr;
@@ -65,14 +68,14 @@ class LLVM_LIBRARY_VISIBILITY WinException : public EHStreamer {
const MachineFunction *MF, const WinEHFuncInfo &FuncInfo,
SmallVectorImpl<std::pair<const MCExpr *, int>> &IPToStateTable);
- /// Emits the label used with llvm.x86.seh.recoverfp, which is used by
+ /// Emits the label used with llvm.eh.recoverfp, which is used by
/// outlined funclets.
void emitEHRegistrationOffsetLabel(const WinEHFuncInfo &FuncInfo,
StringRef FLinkageName);
const MCExpr *create32bitRef(const MCSymbol *Value);
const MCExpr *create32bitRef(const GlobalValue *GV);
- const MCExpr *getLabelPlusOne(const MCSymbol *Label);
+ const MCExpr *getLabel(const MCSymbol *Label);
const MCExpr *getOffset(const MCSymbol *OffsetOf, const MCSymbol *OffsetFrom);
const MCExpr *getOffsetPlusOne(const MCSymbol *OffsetOf,
const MCSymbol *OffsetFrom);