aboutsummaryrefslogtreecommitdiffstats
path: root/lib/CodeGen/AsmPrinter
diff options
context:
space:
mode:
authorStephen Hines <srhines@google.com>2014-04-23 16:57:46 -0700
committerStephen Hines <srhines@google.com>2014-04-24 15:53:16 -0700
commit36b56886974eae4f9c5ebc96befd3e7bfe5de338 (patch)
treee6cfb69fbbd937f450eeb83bfb83b9da3b01275a /lib/CodeGen/AsmPrinter
parent69a8640022b04415ae9fac62f8ab090601d8f889 (diff)
downloadexternal_llvm-36b56886974eae4f9c5ebc96befd3e7bfe5de338.tar.gz
external_llvm-36b56886974eae4f9c5ebc96befd3e7bfe5de338.tar.bz2
external_llvm-36b56886974eae4f9c5ebc96befd3e7bfe5de338.zip
Update to LLVM 3.5a.
Change-Id: Ifadecab779f128e62e430c2b4f6ddd84953ed617
Diffstat (limited to 'lib/CodeGen/AsmPrinter')
-rw-r--r--lib/CodeGen/AsmPrinter/ARMException.cpp68
-rw-r--r--lib/CodeGen/AsmPrinter/Android.mk12
-rw-r--r--lib/CodeGen/AsmPrinter/AsmPrinter.cpp398
-rw-r--r--lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp223
-rw-r--r--lib/CodeGen/AsmPrinter/AsmPrinterHandler.h57
-rw-r--r--lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp73
-rw-r--r--lib/CodeGen/AsmPrinter/ByteStreamer.h71
-rw-r--r--lib/CodeGen/AsmPrinter/CMakeLists.txt3
-rw-r--r--lib/CodeGen/AsmPrinter/DIE.cpp171
-rw-r--r--lib/CodeGen/AsmPrinter/DIE.h829
-rw-r--r--lib/CodeGen/AsmPrinter/DIEHash.cpp224
-rw-r--r--lib/CodeGen/AsmPrinter/DIEHash.h26
-rw-r--r--lib/CodeGen/AsmPrinter/DebugLocEntry.h123
-rw-r--r--lib/CodeGen/AsmPrinter/DebugLocList.h23
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfAccelTable.cpp6
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfAccelTable.h14
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfCFIException.cpp19
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfDebug.cpp2093
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfDebug.h493
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfException.cpp59
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfException.h65
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfUnit.cpp (renamed from lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp)976
-rw-r--r--lib/CodeGen/AsmPrinter/DwarfUnit.h (renamed from lib/CodeGen/AsmPrinter/DwarfCompileUnit.h)399
-rw-r--r--lib/CodeGen/AsmPrinter/ErlangGCPrinter.cpp6
-rw-r--r--lib/CodeGen/AsmPrinter/LLVMBuild.txt2
-rw-r--r--lib/CodeGen/AsmPrinter/OcamlGCPrinter.cpp6
-rw-r--r--lib/CodeGen/AsmPrinter/Win64Exception.cpp17
-rw-r--r--lib/CodeGen/AsmPrinter/WinCodeViewLineTables.cpp336
-rw-r--r--lib/CodeGen/AsmPrinter/WinCodeViewLineTables.h144
29 files changed, 4157 insertions, 2779 deletions
diff --git a/lib/CodeGen/AsmPrinter/ARMException.cpp b/lib/CodeGen/AsmPrinter/ARMException.cpp
index 5d82dd9e9a..403feb4583 100644
--- a/lib/CodeGen/AsmPrinter/ARMException.cpp
+++ b/lib/CodeGen/AsmPrinter/ARMException.cpp
@@ -20,6 +20,7 @@
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/IR/DataLayout.h"
+#include "llvm/IR/Mangler.h"
#include "llvm/IR/Module.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCContext.h"
@@ -30,43 +31,52 @@
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Dwarf.h"
#include "llvm/Support/FormattedStream.h"
-#include "llvm/Target/Mangler.h"
#include "llvm/Target/TargetFrameLowering.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/Target/TargetRegisterInfo.h"
using namespace llvm;
-static cl::opt<bool>
-EnableARMEHABIDescriptors("arm-enable-ehabi-descriptors", cl::Hidden,
- cl::desc("Generate ARM EHABI tables with unwinding descriptors"),
- cl::init(false));
-
-
ARMException::ARMException(AsmPrinter *A)
- : DwarfException(A) {}
+ : DwarfException(A),
+ shouldEmitCFI(false) {}
ARMException::~ARMException() {}
ARMTargetStreamer &ARMException::getTargetStreamer() {
- MCTargetStreamer &TS = Asm->OutStreamer.getTargetStreamer();
+ MCTargetStreamer &TS = *Asm->OutStreamer.getTargetStreamer();
return static_cast<ARMTargetStreamer &>(TS);
}
-void ARMException::EndModule() {
+/// endModule - Emit all exception information that should come after the
+/// content.
+void ARMException::endModule() {
+ if (shouldEmitCFI)
+ Asm->OutStreamer.EmitCFISections(false, true);
}
-/// BeginFunction - Gather pre-function exception information. Assumes it's
+/// beginFunction - Gather pre-function exception information. Assumes it's
/// being emitted immediately after the function entry point.
-void ARMException::BeginFunction(const MachineFunction *MF) {
+void ARMException::beginFunction(const MachineFunction *MF) {
getTargetStreamer().emitFnStart();
if (Asm->MF->getFunction()->needsUnwindTableEntry())
Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("eh_func_begin",
Asm->getFunctionNumber()));
+ // See if we need call frame info.
+ AsmPrinter::CFIMoveType MoveType = Asm->needsCFIMoves();
+ assert(MoveType != AsmPrinter::CFI_M_EH &&
+ "non-EH CFI not yet supported in prologue with EHABI lowering");
+ if (MoveType == AsmPrinter::CFI_M_Debug) {
+ shouldEmitCFI = true;
+ Asm->OutStreamer.EmitCFIStartProc(false);
+ }
}
-/// EndFunction - Gather and emit post-function exception information.
+/// endFunction - Gather and emit post-function exception information.
///
-void ARMException::EndFunction() {
+void ARMException::endFunction(const MachineFunction *) {
+ if (shouldEmitCFI)
+ Asm->OutStreamer.EmitCFIEndProc();
+
ARMTargetStreamer &ATS = getTargetStreamer();
if (!Asm->MF->getFunction()->needsUnwindTableEntry())
ATS.emitCantUnwind();
@@ -74,25 +84,23 @@ void ARMException::EndFunction() {
Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("eh_func_end",
Asm->getFunctionNumber()));
- if (EnableARMEHABIDescriptors) {
- // Map all labels and get rid of any dead landing pads.
- MMI->TidyLandingPads();
+ // Map all labels and get rid of any dead landing pads.
+ MMI->TidyLandingPads();
- if (!MMI->getLandingPads().empty()) {
- // Emit references to personality.
- if (const Function * Personality =
- MMI->getPersonalities()[MMI->getPersonalityIndex()]) {
- MCSymbol *PerSym = Asm->getSymbol(Personality);
- Asm->OutStreamer.EmitSymbolAttribute(PerSym, MCSA_Global);
- ATS.emitPersonality(PerSym);
- }
+ if (!MMI->getLandingPads().empty()) {
+ // Emit references to personality.
+ if (const Function * Personality =
+ MMI->getPersonalities()[MMI->getPersonalityIndex()]) {
+ MCSymbol *PerSym = Asm->getSymbol(Personality);
+ Asm->OutStreamer.EmitSymbolAttribute(PerSym, MCSA_Global);
+ ATS.emitPersonality(PerSym);
+ }
- // Emit .handlerdata directive.
- ATS.emitHandlerData();
+ // Emit .handlerdata directive.
+ ATS.emitHandlerData();
- // Emit actual exception table
- EmitExceptionTable();
- }
+ // Emit actual exception table
+ EmitExceptionTable();
}
}
diff --git a/lib/CodeGen/AsmPrinter/Android.mk b/lib/CodeGen/AsmPrinter/Android.mk
index b2cc47eb92..a725fba2c0 100644
--- a/lib/CodeGen/AsmPrinter/Android.mk
+++ b/lib/CodeGen/AsmPrinter/Android.mk
@@ -16,12 +16,13 @@ LOCAL_SRC_FILES := \
DIEHash.cpp \
DwarfAccelTable.cpp \
DwarfCFIException.cpp \
- DwarfCompileUnit.cpp \
DwarfDebug.cpp \
DwarfException.cpp \
+ DwarfUnit.cpp \
ErlangGCPrinter.cpp \
OcamlGCPrinter.cpp \
- Win64Exception.cpp
+ Win64Exception.cpp \
+ WinCodeViewLineTables.cpp
LOCAL_MODULE:= libLLVMAsmPrinter
@@ -33,6 +34,7 @@ include $(BUILD_HOST_STATIC_LIBRARY)
# For the device
# =====================================================
+ifneq (true,$(DISABLE_LLVM_DEVICE_BUILDS))
include $(CLEAR_VARS)
LOCAL_SRC_FILES := \
@@ -44,12 +46,13 @@ LOCAL_SRC_FILES := \
DIEHash.cpp \
DwarfAccelTable.cpp \
DwarfCFIException.cpp \
- DwarfCompileUnit.cpp \
DwarfDebug.cpp \
DwarfException.cpp \
+ DwarfUnit.cpp \
ErlangGCPrinter.cpp \
+ OcamlGCPrinter.cpp \
Win64Exception.cpp \
- $(LOCAL_SRC_FILES)
+ WinCodeViewLineTables.cpp
LOCAL_MODULE:= libLLVMAsmPrinter
@@ -58,3 +61,4 @@ LOCAL_MODULE_TAGS := optional
include $(LLVM_DEVICE_BUILD_MK)
include $(LLVM_GEN_INTRINSICS_MK)
include $(BUILD_STATIC_LIBRARY)
+endif
diff --git a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
index 308b0e091a..c3afc8ba8c 100644
--- a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -15,19 +15,21 @@
#include "llvm/CodeGen/AsmPrinter.h"
#include "DwarfDebug.h"
#include "DwarfException.h"
+#include "WinCodeViewLineTables.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Analysis/ConstantFolding.h"
-#include "llvm/Assembly/Writer.h"
#include "llvm/CodeGen/GCMetadataPrinter.h"
#include "llvm/CodeGen/MachineConstantPool.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/MachineInstrBundle.h"
#include "llvm/CodeGen/MachineJumpTableInfo.h"
#include "llvm/CodeGen/MachineLoopInfo.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
-#include "llvm/DebugInfo.h"
#include "llvm/IR/DataLayout.h"
+#include "llvm/IR/DebugInfo.h"
+#include "llvm/IR/Mangler.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Operator.h"
#include "llvm/MC/MCAsmInfo.h"
@@ -41,19 +43,20 @@
#include "llvm/Support/Format.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/Timer.h"
-#include "llvm/Target/Mangler.h"
#include "llvm/Target/TargetFrameLowering.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetLowering.h"
#include "llvm/Target/TargetLoweringObjectFile.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/Target/TargetRegisterInfo.h"
+#include "llvm/Target/TargetSubtargetInfo.h"
#include "llvm/Transforms/Utils/GlobalStatus.h"
using namespace llvm;
static const char *const DWARFGroupName = "DWARF Emission";
-static const char *const DbgTimerName = "DWARF Debug Writer";
+static const char *const DbgTimerName = "Debug Info Emission";
static const char *const EHTimerName = "DWARF Exception Writer";
+static const char *const CodeViewLineTablesGroupName = "CodeView Line Tables";
STATISTIC(EmittedInsts, "Number of machine instrs printed");
@@ -99,14 +102,14 @@ AsmPrinter::AsmPrinter(TargetMachine &tm, MCStreamer &Streamer)
OutContext(Streamer.getContext()),
OutStreamer(Streamer),
LastMI(0), LastFn(0), Counter(~0U), SetCounter(0) {
- DD = 0; DE = 0; MMI = 0; LI = 0; MF = 0;
+ DD = 0; MMI = 0; LI = 0; MF = 0;
CurrentFnSym = CurrentFnSymForSize = 0;
GCMetadataPrinters = 0;
VerboseAsm = Streamer.isVerboseAsm();
}
AsmPrinter::~AsmPrinter() {
- assert(DD == 0 && DE == 0 && "Debug/EH info didn't get finalized");
+ assert(DD == 0 && Handlers.empty() && "Debug/EH info didn't get finalized");
if (GCMetadataPrinters != 0) {
gcp_map_type &GCMap = getGCMap(GCMetadataPrinters);
@@ -135,6 +138,14 @@ const DataLayout &AsmPrinter::getDataLayout() const {
return *TM.getDataLayout();
}
+const MCSubtargetInfo &AsmPrinter::getSubtargetInfo() const {
+ return TM.getSubtarget<MCSubtargetInfo>();
+}
+
+void AsmPrinter::EmitToStreamer(MCStreamer &S, const MCInst &Inst) {
+ S.EmitInstruction(Inst, getSubtargetInfo());
+}
+
StringRef AsmPrinter::getTargetTriple() const {
return TM.getTargetTriple();
}
@@ -163,9 +174,28 @@ bool AsmPrinter::doInitialization(Module &M) {
const_cast<TargetLoweringObjectFile&>(getObjFileLowering())
.Initialize(OutContext, TM);
- OutStreamer.InitStreamer();
+ OutStreamer.InitSections();
- Mang = new Mangler(&TM);
+ Mang = new Mangler(TM.getDataLayout());
+
+ // Emit the version-min deplyment target directive if needed.
+ //
+ // FIXME: If we end up with a collection of these sorts of Darwin-specific
+ // or ELF-specific things, it may make sense to have a platform helper class
+ // that will work with the target helper class. For now keep it here, as the
+ // alternative is duplicated code in each of the target asm printers that
+ // use the directive, where it would need the same conditionalization
+ // anyway.
+ Triple TT(getTargetTriple());
+ if (TT.isOSDarwin()) {
+ unsigned Major, Minor, Update;
+ TT.getOSVersion(Major, Minor, Update);
+ // If there is a version specified, Major will be non-zero.
+ if (Major)
+ OutStreamer.EmitVersionMin((TT.isMacOSX() ?
+ MCVM_OSXVersionMin : MCVM_IOSVersionMin),
+ Major, Minor, Update);
+ }
// Allow the target to emit any magic that it wants at the start of the file.
EmitStartOfAsmFile(M);
@@ -192,25 +222,65 @@ bool AsmPrinter::doInitialization(Module &M) {
OutStreamer.AddBlankLine();
}
- if (MAI->doesSupportDebugInformation())
- DD = new DwarfDebug(this, &M);
+ if (MAI->doesSupportDebugInformation()) {
+ if (Triple(TM.getTargetTriple()).isKnownWindowsMSVCEnvironment()) {
+ Handlers.push_back(HandlerInfo(new WinCodeViewLineTables(this),
+ DbgTimerName,
+ CodeViewLineTablesGroupName));
+ } else {
+ DD = new DwarfDebug(this, &M);
+ Handlers.push_back(HandlerInfo(DD, DbgTimerName, DWARFGroupName));
+ }
+ }
+ DwarfException *DE = 0;
switch (MAI->getExceptionHandlingType()) {
case ExceptionHandling::None:
- return false;
+ break;
case ExceptionHandling::SjLj:
case ExceptionHandling::DwarfCFI:
DE = new DwarfCFIException(this);
- return false;
+ break;
case ExceptionHandling::ARM:
DE = new ARMException(this);
- return false;
+ break;
case ExceptionHandling::Win64:
DE = new Win64Exception(this);
+ break;
+ }
+ if (DE)
+ Handlers.push_back(HandlerInfo(DE, EHTimerName, DWARFGroupName));
+ return false;
+}
+
+static bool canBeHidden(const GlobalValue *GV, const MCAsmInfo &MAI) {
+ GlobalValue::LinkageTypes Linkage = GV->getLinkage();
+ if (Linkage != GlobalValue::LinkOnceODRLinkage)
+ return false;
+
+ if (!MAI.hasWeakDefCanBeHiddenDirective())
+ return false;
+
+ if (GV->hasUnnamedAddr())
+ return true;
+
+ // This is only used for MachO, so right now it doesn't really matter how
+ // we handle alias. Revisit this once the MachO linker implements aliases.
+ if (isa<GlobalAlias>(GV))
return false;
+
+ // If it is a non constant variable, it needs to be uniqued across shared
+ // objects.
+ if (const GlobalVariable *Var = dyn_cast<GlobalVariable>(GV)) {
+ if (!Var->isConstant())
+ return false;
}
- llvm_unreachable("Unknown exception type.");
+ GlobalStatus GS;
+ if (!GlobalStatus::analyzeGlobal(GV, GS) && !GS.IsCompared)
+ return true;
+
+ return false;
}
void AsmPrinter::EmitLinkage(const GlobalValue *GV, MCSymbol *GVSym) const {
@@ -221,29 +291,16 @@ void AsmPrinter::EmitLinkage(const GlobalValue *GV, MCSymbol *GVSym) const {
case GlobalValue::LinkOnceODRLinkage:
case GlobalValue::WeakAnyLinkage:
case GlobalValue::WeakODRLinkage:
- case GlobalValue::LinkerPrivateWeakLinkage:
- if (MAI->getWeakDefDirective() != 0) {
+ if (MAI->hasWeakDefDirective()) {
// .globl _foo
OutStreamer.EmitSymbolAttribute(GVSym, MCSA_Global);
- bool CanBeHidden = false;
-
- if (Linkage == GlobalValue::LinkOnceODRLinkage) {
- if (GV->hasUnnamedAddr()) {
- CanBeHidden = true;
- } else {
- GlobalStatus GS;
- if (!GlobalStatus::analyzeGlobal(GV, GS) && !GS.IsCompared)
- CanBeHidden = true;
- }
- }
-
- if (!CanBeHidden)
+ if (!canBeHidden(GV, *MAI))
// .weak_definition _foo
OutStreamer.EmitSymbolAttribute(GVSym, MCSA_WeakDefinition);
else
OutStreamer.EmitSymbolAttribute(GVSym, MCSA_WeakDefAutoPrivate);
- } else if (MAI->getLinkOnceDirective() != 0) {
+ } else if (MAI->hasLinkOnceDirective()) {
// .globl _foo
OutStreamer.EmitSymbolAttribute(GVSym, MCSA_Global);
//NOTE: linkonce is handled by the section the symbol was assigned to.
@@ -252,7 +309,6 @@ void AsmPrinter::EmitLinkage(const GlobalValue *GV, MCSymbol *GVSym) const {
OutStreamer.EmitSymbolAttribute(GVSym, MCSA_Weak);
}
return;
- case GlobalValue::DLLExportLinkage:
case GlobalValue::AppendingLinkage:
// FIXME: appending linkage variables should go into a section of
// their name or something. For now, just emit them as external.
@@ -263,19 +319,22 @@ void AsmPrinter::EmitLinkage(const GlobalValue *GV, MCSymbol *GVSym) const {
return;
case GlobalValue::PrivateLinkage:
case GlobalValue::InternalLinkage:
- case GlobalValue::LinkerPrivateLinkage:
return;
case GlobalValue::AvailableExternallyLinkage:
llvm_unreachable("Should never emit this");
- case GlobalValue::DLLImportLinkage:
case GlobalValue::ExternalWeakLinkage:
llvm_unreachable("Don't know how to emit these");
}
llvm_unreachable("Unknown linkage type!");
}
+void AsmPrinter::getNameWithPrefix(SmallVectorImpl<char> &Name,
+ const GlobalValue *GV) const {
+ TM.getNameWithPrefix(Name, GV, *Mang);
+}
+
MCSymbol *AsmPrinter::getSymbol(const GlobalValue *GV) const {
- return getObjFileLowering().getSymbol(*Mang, GV);
+ return TM.getSymbol(GV, *Mang);
}
/// EmitGlobalVariable - Emit the specified global variable to the .s file.
@@ -286,7 +345,7 @@ void AsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) {
return;
if (isVerbose()) {
- WriteAsOperand(OutStreamer.GetCommentOS(), GV,
+ GV->printAsOperand(OutStreamer.GetCommentOS(),
/*PrintType=*/false, GV->getParent());
OutStreamer.GetCommentOS() << '\n';
}
@@ -311,8 +370,11 @@ void AsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) {
// sections and expected to be contiguous (e.g. ObjC metadata).
unsigned AlignLog = getGVAlignmentLog2(GV, *DL);
- if (DD)
- DD->setSymbolSize(GVSym, Size);
+ for (unsigned I = 0, E = Handlers.size(); I != E; ++I) {
+ const HandlerInfo &OI = Handlers[I];
+ NamedRegionTimer T(OI.TimerName, OI.TimerGroupName, TimePassesIsEnabled);
+ OI.Handler->setSymbolSize(GVSym, Size);
+ }
// Handle common and BSS local symbols (.lcomm).
if (GVKind.isCommon() || GVKind.isBSSLocal()) {
@@ -332,7 +394,7 @@ void AsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) {
// Handle local BSS symbols.
if (MAI->hasMachoZeroFillDirective()) {
const MCSection *TheSection =
- getObjFileLowering().SectionForGlobal(GV, GVKind, Mang, TM);
+ getObjFileLowering().SectionForGlobal(GV, GVKind, *Mang, TM);
// .zerofill __DATA, __bss, _foo, 400, 5
OutStreamer.EmitZerofill(TheSection, GVSym, Size, Align);
return;
@@ -361,7 +423,7 @@ void AsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) {
}
const MCSection *TheSection =
- getObjFileLowering().SectionForGlobal(GV, GVKind, Mang, TM);
+ getObjFileLowering().SectionForGlobal(GV, GVKind, *Mang, TM);
// Handle the zerofill directive on darwin, which is a special form of BSS
// emission.
@@ -452,7 +514,8 @@ void AsmPrinter::EmitFunctionHeader() {
// Print the 'header' of function.
const Function *F = MF->getFunction();
- OutStreamer.SwitchSection(getObjFileLowering().SectionForGlobal(F, Mang, TM));
+ OutStreamer.SwitchSection(
+ getObjFileLowering().SectionForGlobal(F, *Mang, TM));
EmitVisibility(CurrentFnSym, F->getVisibility());
EmitLinkage(F, CurrentFnSym);
@@ -462,7 +525,7 @@ void AsmPrinter::EmitFunctionHeader() {
OutStreamer.EmitSymbolAttribute(CurrentFnSym, MCSA_ELF_TypeFunction);
if (isVerbose()) {
- WriteAsOperand(OutStreamer.GetCommentOS(), F,
+ F->printAsOperand(OutStreamer.GetCommentOS(),
/*PrintType=*/false, F->getParent());
OutStreamer.GetCommentOS() << '\n';
}
@@ -482,13 +545,10 @@ void AsmPrinter::EmitFunctionHeader() {
}
// Emit pre-function debug and/or EH information.
- if (DE) {
- NamedRegionTimer T(EHTimerName, DWARFGroupName, TimePassesIsEnabled);
- DE->BeginFunction(MF);
- }
- if (DD) {
- NamedRegionTimer T(DbgTimerName, DWARFGroupName, TimePassesIsEnabled);
- DD->beginFunction(MF);
+ for (unsigned I = 0, E = Handlers.size(); I != E; ++I) {
+ const HandlerInfo &OI = Handlers[I];
+ NamedRegionTimer T(OI.TimerName, OI.TimerGroupName, TimePassesIsEnabled);
+ OI.Handler->beginFunction(MF);
}
// Emit the prefix data.
@@ -576,10 +636,9 @@ static bool emitDebugValueComment(const MachineInstr *MI, AsmPrinter &AP) {
SmallString<128> Str;
raw_svector_ostream OS(Str);
- OS << '\t' << AP.MAI->getCommentString() << "DEBUG_VALUE: ";
+ OS << "DEBUG_VALUE: ";
- // cast away const; DIetc do not take const operands for some reason.
- DIVariable V(const_cast<MDNode*>(MI->getOperand(2).getMetadata()));
+ DIVariable V(MI->getOperand(2).getMetadata());
if (V.getContext().isSubprogram()) {
StringRef Name = DISubprogram(V.getContext()).getDisplayName();
if (!Name.empty())
@@ -625,7 +684,7 @@ static bool emitDebugValueComment(const MachineInstr *MI, AsmPrinter &AP) {
// Suppress offset, it is not meaningful here.
OS << "undef";
// NOTE: Want this comment at start of line, don't emit with AddComment.
- AP.OutStreamer.EmitRawText(OS.str());
+ AP.OutStreamer.emitRawComment(OS.str());
return true;
}
if (Deref)
@@ -637,7 +696,7 @@ static bool emitDebugValueComment(const MachineInstr *MI, AsmPrinter &AP) {
OS << '+' << Offset << ']';
// NOTE: Want this comment at start of line, don't emit with AddComment.
- AP.OutStreamer.EmitRawText(OS.str());
+ AP.OutStreamer.emitRawComment(OS.str());
return true;
}
@@ -657,14 +716,11 @@ bool AsmPrinter::needsSEHMoves() {
MF->getFunction()->needsUnwindTableEntry();
}
-bool AsmPrinter::needsRelocationsForDwarfStringPool() const {
- return MAI->doesDwarfUseRelocationsAcrossSections();
-}
-
-void AsmPrinter::emitPrologLabel(const MachineInstr &MI) {
- const MCSymbol *Label = MI.getOperand(0).getMCSymbol();
-
- if (MAI->getExceptionHandlingType() != ExceptionHandling::DwarfCFI)
+void AsmPrinter::emitCFIInstruction(const MachineInstr &MI) {
+ ExceptionHandling::ExceptionsType ExceptionHandlingType =
+ MAI->getExceptionHandlingType();
+ if (ExceptionHandlingType != ExceptionHandling::DwarfCFI &&
+ ExceptionHandlingType != ExceptionHandling::ARM)
return;
if (needsCFIMoves() == CFI_M_None)
@@ -675,16 +731,9 @@ void AsmPrinter::emitPrologLabel(const MachineInstr &MI) {
const MachineModuleInfo &MMI = MF->getMMI();
const std::vector<MCCFIInstruction> &Instrs = MMI.getFrameInstructions();
- bool FoundOne = false;
- (void)FoundOne;
- for (std::vector<MCCFIInstruction>::const_iterator I = Instrs.begin(),
- E = Instrs.end(); I != E; ++I) {
- if (I->getLabel() == Label) {
- emitCFIInstruction(*I);
- FoundOne = true;
- }
- }
- assert(FoundOne);
+ unsigned CFIIndex = MI.getOperand(0).getCFIIndex();
+ const MCCFIInstruction &CFI = Instrs[CFIIndex];
+ emitCFIInstruction(CFI);
}
/// EmitFunctionBody - This method emits the body and trailer for a
@@ -693,7 +742,7 @@ void AsmPrinter::EmitFunctionBody() {
// Emit target-specific gunk before the function body.
EmitFunctionBodyStart();
- bool ShouldPrintDebugScopes = DD && MMI->hasDebugInfo();
+ bool ShouldPrintDebugScopes = MMI->hasDebugInfo();
// Print out code for the function.
bool HasAnyRealCode = false;
@@ -707,23 +756,27 @@ void AsmPrinter::EmitFunctionBody() {
LastMI = II;
// Print the assembly for the instruction.
- if (!II->isLabel() && !II->isImplicitDef() && !II->isKill() &&
+ if (!II->isPosition() && !II->isImplicitDef() && !II->isKill() &&
!II->isDebugValue()) {
HasAnyRealCode = true;
++EmittedInsts;
}
if (ShouldPrintDebugScopes) {
- NamedRegionTimer T(DbgTimerName, DWARFGroupName, TimePassesIsEnabled);
- DD->beginInstruction(II);
+ for (unsigned III = 0, EEE = Handlers.size(); III != EEE; ++III) {
+ const HandlerInfo &OI = Handlers[III];
+ NamedRegionTimer T(OI.TimerName, OI.TimerGroupName,
+ TimePassesIsEnabled);
+ OI.Handler->beginInstruction(II);
+ }
}
if (isVerbose())
emitComments(*II, OutStreamer.GetCommentOS());
switch (II->getOpcode()) {
- case TargetOpcode::PROLOG_LABEL:
- emitPrologLabel(*II);
+ case TargetOpcode::CFI_INSTRUCTION:
+ emitCFIInstruction(*II);
break;
case TargetOpcode::EH_LABEL:
@@ -746,16 +799,17 @@ void AsmPrinter::EmitFunctionBody() {
if (isVerbose()) emitKill(II, *this);
break;
default:
- if (!TM.hasMCUseLoc())
- MCLineEntry::Make(&OutStreamer, getCurrentSection());
-
EmitInstruction(II);
break;
}
if (ShouldPrintDebugScopes) {
- NamedRegionTimer T(DbgTimerName, DWARFGroupName, TimePassesIsEnabled);
- DD->endInstruction(II);
+ for (unsigned III = 0, EEE = Handlers.size(); III != EEE; ++III) {
+ const HandlerInfo &OI = Handlers[III];
+ NamedRegionTimer T(OI.TimerName, OI.TimerGroupName,
+ TimePassesIsEnabled);
+ OI.Handler->endInstruction();
+ }
}
}
}
@@ -765,7 +819,7 @@ void AsmPrinter::EmitFunctionBody() {
// label equaling the end of function label and an invalid "row" in the
// FDE. We need to emit a noop in this situation so that the FDE's rows are
// valid.
- bool RequiresNoop = LastMI && LastMI->isPrologLabel();
+ bool RequiresNoop = LastMI && LastMI->isCFIInstruction();
// If the function is empty and the object file uses .subsections_via_symbols,
// then we need to emit *something* to the function body to prevent the
@@ -775,7 +829,7 @@ void AsmPrinter::EmitFunctionBody() {
TM.getInstrInfo()->getNoopForMachoTarget(Noop);
if (Noop.getOpcode()) {
OutStreamer.AddComment("avoids zero-length function");
- OutStreamer.EmitInstruction(Noop);
+ OutStreamer.EmitInstruction(Noop, getSubtargetInfo());
} else // Target not mc-ized yet.
OutStreamer.EmitRawText(StringRef("\tnop\n"));
}
@@ -811,14 +865,11 @@ void AsmPrinter::EmitFunctionBody() {
OutStreamer.EmitELFSize(CurrentFnSym, SizeExp);
}
- // Emit post-function debug information.
- if (DD) {
- NamedRegionTimer T(DbgTimerName, DWARFGroupName, TimePassesIsEnabled);
- DD->endFunction(MF);
- }
- if (DE) {
- NamedRegionTimer T(EHTimerName, DWARFGroupName, TimePassesIsEnabled);
- DE->EndFunction();
+ // Emit post-function debug and/or EH information.
+ for (unsigned I = 0, E = Handlers.size(); I != E; ++I) {
+ const HandlerInfo &OI = Handlers[I];
+ NamedRegionTimer T(OI.TimerName, OI.TimerGroupName, TimePassesIsEnabled);
+ OI.Handler->endFunction(MF);
}
MMI->EndFunction();
@@ -828,56 +879,6 @@ void AsmPrinter::EmitFunctionBody() {
OutStreamer.AddBlankLine();
}
-/// EmitDwarfRegOp - Emit dwarf register operation.
-void AsmPrinter::EmitDwarfRegOp(const MachineLocation &MLoc,
- bool Indirect) const {
- const TargetRegisterInfo *TRI = TM.getRegisterInfo();
- int Reg = TRI->getDwarfRegNum(MLoc.getReg(), false);
-
- for (MCSuperRegIterator SR(MLoc.getReg(), TRI); SR.isValid() && Reg < 0;
- ++SR) {
- Reg = TRI->getDwarfRegNum(*SR, false);
- // FIXME: Get the bit range this register uses of the superregister
- // so that we can produce a DW_OP_bit_piece
- }
-
- // FIXME: Handle cases like a super register being encoded as
- // DW_OP_reg 32 DW_OP_piece 4 DW_OP_reg 33
-
- // FIXME: We have no reasonable way of handling errors in here. The
- // caller might be in the middle of an dwarf expression. We should
- // probably assert that Reg >= 0 once debug info generation is more mature.
-
- if (MLoc.isIndirect() || Indirect) {
- if (Reg < 32) {
- OutStreamer.AddComment(
- dwarf::OperationEncodingString(dwarf::DW_OP_breg0 + Reg));
- EmitInt8(dwarf::DW_OP_breg0 + Reg);
- } else {
- OutStreamer.AddComment("DW_OP_bregx");
- EmitInt8(dwarf::DW_OP_bregx);
- OutStreamer.AddComment(Twine(Reg));
- EmitULEB128(Reg);
- }
- EmitSLEB128(!MLoc.isIndirect() ? 0 : MLoc.getOffset());
- if (MLoc.isIndirect() && Indirect)
- EmitInt8(dwarf::DW_OP_deref);
- } else {
- if (Reg < 32) {
- OutStreamer.AddComment(
- dwarf::OperationEncodingString(dwarf::DW_OP_reg0 + Reg));
- EmitInt8(dwarf::DW_OP_reg0 + Reg);
- } else {
- OutStreamer.AddComment("DW_OP_regx");
- EmitInt8(dwarf::DW_OP_regx);
- OutStreamer.AddComment(Twine(Reg));
- EmitULEB128(Reg);
- }
- }
-
- // FIXME: Produce a DW_OP_bit_piece if we used a superregister
-}
-
bool AsmPrinter::doFinalization(Module &M) {
// Emit global variables.
for (Module::const_global_iterator I = M.global_begin(), E = M.global_end();
@@ -901,26 +902,21 @@ bool AsmPrinter::doFinalization(Module &M) {
SmallVector<Module::ModuleFlagEntry, 8> ModuleFlags;
M.getModuleFlagsMetadata(ModuleFlags);
if (!ModuleFlags.empty())
- getObjFileLowering().emitModuleFlags(OutStreamer, ModuleFlags, Mang, TM);
+ getObjFileLowering().emitModuleFlags(OutStreamer, ModuleFlags, *Mang, TM);
// Make sure we wrote out everything we need.
OutStreamer.Flush();
// Finalize debug and EH information.
- if (DE) {
- {
- NamedRegionTimer T(EHTimerName, DWARFGroupName, TimePassesIsEnabled);
- DE->EndModule();
- }
- delete DE; DE = 0;
- }
- if (DD) {
- {
- NamedRegionTimer T(DbgTimerName, DWARFGroupName, TimePassesIsEnabled);
- DD->endModule();
- }
- delete DD; DD = 0;
+ for (unsigned I = 0, E = Handlers.size(); I != E; ++I) {
+ const HandlerInfo &OI = Handlers[I];
+ NamedRegionTimer T(OI.TimerName, OI.TimerGroupName,
+ TimePassesIsEnabled);
+ OI.Handler->endModule();
+ delete OI.Handler;
}
+ Handlers.clear();
+ DD = 0;
// If the target wants to know about weak references, print them all.
if (MAI->getWeakRefDirective()) {
@@ -949,11 +945,7 @@ bool AsmPrinter::doFinalization(Module &M) {
MCSymbol *Name = getSymbol(I);
const GlobalValue *GV = I->getAliasedGlobal();
- if (GV->isDeclaration()) {
- report_fatal_error(Name->getName() +
- ": Target doesn't support aliases to declarations");
- }
-
+ assert(!GV->isDeclaration());
MCSymbol *Target = getSymbol(GV);
if (I->hasExternalLinkage() || !MAI->getWeakRefDirective())
@@ -1106,6 +1098,7 @@ void AsmPrinter::EmitConstantPool() {
/// by the current function to the current output stream.
///
void AsmPrinter::EmitJumpTableInfo() {
+ const DataLayout *DL = MF->getTarget().getDataLayout();
const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo();
if (MJTI == 0) return;
if (MJTI->getEntryKind() == MachineJumpTableInfo::EK_Inline) return;
@@ -1125,7 +1118,8 @@ void AsmPrinter::EmitJumpTableInfo() {
// FIXME: this isn't the right predicate, should be based on the MCSection
// for the function.
F->isWeakForLinker()) {
- OutStreamer.SwitchSection(getObjFileLowering().SectionForGlobal(F,Mang,TM));
+ OutStreamer.SwitchSection(
+ getObjFileLowering().SectionForGlobal(F, *Mang, TM));
} else {
// Otherwise, drop it in the readonly section.
const MCSection *ReadOnlySection =
@@ -1171,7 +1165,7 @@ void AsmPrinter::EmitJumpTableInfo() {
// before each jump table. The first label is never referenced, but tells
// the assembler and linker the extents of the jump table object. The
// second label is actually referenced by the code.
- if (JTInDiffSection && MAI->getLinkerPrivateGlobalPrefix()[0])
+ if (JTInDiffSection && DL->hasLinkerPrivateGlobalPrefix())
// FIXME: This doesn't have to have any specific name, just any randomly
// named and numbered 'l' label would work. Simplify GetJTISymbol.
OutStreamer.EmitLabel(GetJTISymbol(JTI, true));
@@ -1309,7 +1303,7 @@ void AsmPrinter::EmitLLVMUsedList(const ConstantArray *InitList) {
for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) {
const GlobalValue *GV =
dyn_cast<GlobalValue>(InitList->getOperand(i)->stripPointerCasts());
- if (GV && getObjFileLowering().shouldEmitUsedDirectiveFor(GV, Mang))
+ if (GV)
OutStreamer.EmitSymbolAttribute(getSymbol(GV), MCSA_NoDeadStrip);
}
}
@@ -1366,7 +1360,7 @@ void AsmPrinter::EmitModuleIdents(Module &M) {
if (const NamedMDNode *NMD = M.getNamedMetadata("llvm.ident")) {
for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) {
const MDNode *N = NMD->getOperand(i);
- assert(N->getNumOperands() == 1 &&
+ assert(N->getNumOperands() == 1 &&
"llvm.ident metadata entry can have only one operand");
const MDString *S = cast<MDString>(N->getOperand(0));
OutStreamer.EmitIdent(S->getString());
@@ -1422,8 +1416,8 @@ void AsmPrinter::EmitLabelDifference(const MCSymbol *Hi, const MCSymbol *Lo,
/// where the size in bytes of the directive is specified by Size and Hi/Lo
/// specify the labels. This implicitly uses .set if it is available.
void AsmPrinter::EmitLabelOffsetDifference(const MCSymbol *Hi, uint64_t Offset,
- const MCSymbol *Lo, unsigned Size)
- const {
+ const MCSymbol *Lo,
+ unsigned Size) const {
// Emit Hi+Offset - Lo
// Get the Hi+Offset expression.
@@ -1452,8 +1446,8 @@ void AsmPrinter::EmitLabelOffsetDifference(const MCSymbol *Hi, uint64_t Offset,
/// where the size in bytes of the directive is specified by Size and Label
/// specifies the label. This implicitly uses .set if it is available.
void AsmPrinter::EmitLabelPlusOffset(const MCSymbol *Label, uint64_t Offset,
- unsigned Size, bool IsSectionRelative)
- const {
+ unsigned Size,
+ bool IsSectionRelative) const {
if (MAI->needsDwarfSectionOffsetDirective() && IsSectionRelative) {
OutStreamer.EmitCOFFSecRel32(Label);
return;
@@ -1462,14 +1456,12 @@ void AsmPrinter::EmitLabelPlusOffset(const MCSymbol *Label, uint64_t Offset,
// Emit Label+Offset (or just Label if Offset is zero)
const MCExpr *Expr = MCSymbolRefExpr::Create(Label, OutContext);
if (Offset)
- Expr = MCBinaryExpr::CreateAdd(Expr,
- MCConstantExpr::Create(Offset, OutContext),
- OutContext);
+ Expr = MCBinaryExpr::CreateAdd(
+ Expr, MCConstantExpr::Create(Offset, OutContext), OutContext);
OutStreamer.EmitValue(Expr, Size);
}
-
//===----------------------------------------------------------------------===//
// EmitAlignment - Emit an alignment directive to the specified power of
@@ -1486,7 +1478,7 @@ void AsmPrinter::EmitAlignment(unsigned NumBits, const GlobalValue *GV) const {
if (getCurrentSection()->getKind().isText())
OutStreamer.EmitCodeAlignment(1 << NumBits);
else
- OutStreamer.EmitValueToAlignment(1 << NumBits, 0, 1, 0);
+ OutStreamer.EmitValueToAlignment(1 << NumBits);
}
//===----------------------------------------------------------------------===//
@@ -1515,6 +1507,11 @@ static const MCExpr *lowerConstant(const Constant *CV, AsmPrinter &AP) {
llvm_unreachable("Unknown constant value to lower!");
}
+ if (const MCExpr *RelocExpr =
+ AP.getObjFileLowering().getExecutableRelativeSymbol(CE, *AP.Mang,
+ AP.TM))
+ return RelocExpr;
+
switch (CE->getOpcode()) {
default:
// If the code isn't optimized, there may be outstanding folding
@@ -1530,7 +1527,7 @@ static const MCExpr *lowerConstant(const Constant *CV, AsmPrinter &AP) {
std::string S;
raw_string_ostream OS(S);
OS << "Unsupported expression in static initializer: ";
- WriteAsOperand(OS, CE, /*PrintType=*/false,
+ CE->printAsOperand(OS, /*PrintType=*/false,
!AP.MF ? 0 : AP.MF->getFunction()->getParent());
report_fatal_error(OS.str());
}
@@ -1994,15 +1991,17 @@ void AsmPrinter::printOffset(int64_t Offset, raw_ostream &OS) const {
/// GetTempSymbol - Return the MCSymbol corresponding to the assembler
/// temporary label with the specified stem and unique ID.
-MCSymbol *AsmPrinter::GetTempSymbol(StringRef Name, unsigned ID) const {
- return OutContext.GetOrCreateSymbol(Twine(MAI->getPrivateGlobalPrefix()) +
+MCSymbol *AsmPrinter::GetTempSymbol(Twine Name, unsigned ID) const {
+ const DataLayout *DL = TM.getDataLayout();
+ return OutContext.GetOrCreateSymbol(Twine(DL->getPrivateGlobalPrefix()) +
Name + Twine(ID));
}
/// GetTempSymbol - Return an assembler temporary label with the specified
/// stem.
-MCSymbol *AsmPrinter::GetTempSymbol(StringRef Name) const {
- return OutContext.GetOrCreateSymbol(Twine(MAI->getPrivateGlobalPrefix())+
+MCSymbol *AsmPrinter::GetTempSymbol(Twine Name) const {
+ const DataLayout *DL = TM.getDataLayout();
+ return OutContext.GetOrCreateSymbol(Twine(DL->getPrivateGlobalPrefix())+
Name);
}
@@ -2017,8 +2016,9 @@ MCSymbol *AsmPrinter::GetBlockAddressSymbol(const BasicBlock *BB) const {
/// GetCPISymbol - Return the symbol for the specified constant pool entry.
MCSymbol *AsmPrinter::GetCPISymbol(unsigned CPID) const {
+ const DataLayout *DL = TM.getDataLayout();
return OutContext.GetOrCreateSymbol
- (Twine(MAI->getPrivateGlobalPrefix()) + "CPI" + Twine(getFunctionNumber())
+ (Twine(DL->getPrivateGlobalPrefix()) + "CPI" + Twine(getFunctionNumber())
+ "_" + Twine(CPID));
}
@@ -2030,21 +2030,16 @@ MCSymbol *AsmPrinter::GetJTISymbol(unsigned JTID, bool isLinkerPrivate) const {
/// GetJTSetSymbol - Return the symbol for the specified jump table .set
/// FIXME: privatize to AsmPrinter.
MCSymbol *AsmPrinter::GetJTSetSymbol(unsigned UID, unsigned MBBID) const {
+ const DataLayout *DL = TM.getDataLayout();
return OutContext.GetOrCreateSymbol
- (Twine(MAI->getPrivateGlobalPrefix()) + Twine(getFunctionNumber()) + "_" +
+ (Twine(DL->getPrivateGlobalPrefix()) + Twine(getFunctionNumber()) + "_" +
Twine(UID) + "_set_" + Twine(MBBID));
}
-/// GetSymbolWithGlobalValueBase - Return the MCSymbol for a symbol with
-/// global value name as its base, with the specified suffix, and where the
-/// symbol is forced to have private linkage if ForcePrivate is true.
-MCSymbol *AsmPrinter::GetSymbolWithGlobalValueBase(const GlobalValue *GV,
- StringRef Suffix,
- bool ForcePrivate) const {
- SmallString<60> NameStr;
- Mang->getNameWithPrefix(NameStr, GV, ForcePrivate);
- NameStr.append(Suffix.begin(), Suffix.end());
- return OutContext.GetOrCreateSymbol(NameStr.str());
+MCSymbol *AsmPrinter::getSymbolWithGlobalValueBase(const GlobalValue *GV,
+ StringRef Suffix) const {
+ return getObjFileLowering().getSymbolWithGlobalValueBase(GV, Suffix, *Mang,
+ TM);
}
/// GetExternalSymbolSymbol - Return the MCSymbol for the specified
@@ -2155,10 +2150,9 @@ void AsmPrinter::EmitBasicBlockStart(const MachineBasicBlock *MBB) const {
// Print the main label for the block.
if (MBB->pred_empty() || isBlockOnlyReachableByFallthrough(MBB)) {
- if (isVerbose() && OutStreamer.hasRawTextSupport()) {
+ if (isVerbose()) {
// NOTE: Want this comment at start of line, don't emit with AddComment.
- OutStreamer.EmitRawText(Twine(MAI->getCommentString()) + " BB#" +
- Twine(MBB->getNumber()) + ":");
+ OutStreamer.emitRawComment(" BB#" + Twine(MBB->getNumber()) + ":", false);
}
} else {
OutStreamer.EmitLabel(MBB->getSymbol());
@@ -2221,14 +2215,13 @@ isBlockOnlyReachableByFallthrough(const MachineBasicBlock *MBB) const {
if (!MI.isBranch() || MI.isIndirectBranch())
return false;
- // If we are the operands of one of the branches, this is not
- // a fall through.
- for (MachineInstr::mop_iterator OI = MI.operands_begin(),
- OE = MI.operands_end(); OI != OE; ++OI) {
- const MachineOperand& OP = *OI;
- if (OP.isJTI())
+ // If we are the operands of one of the branches, this is not a fall
+ // through. Note that targets with delay slots will usually bundle
+ // terminators with the delay slot instruction.
+ for (ConstMIBundleOperands OP(&MI); OP.isValid(); ++OP) {
+ if (OP->isJTI())
return false;
- if (OP.isMBB() && OP.getMBB() == MBB)
+ if (OP->isMBB() && OP->getMBB() == MBB)
return false;
}
}
@@ -2261,3 +2254,6 @@ GCMetadataPrinter *AsmPrinter::GetOrCreateGCPrinter(GCStrategy *S) {
report_fatal_error("no GCMetadataPrinter registered for GC: " + Twine(Name));
}
+
+/// Pin vtable to this file.
+AsmPrinterHandler::~AsmPrinterHandler() {}
diff --git a/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp b/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp
index b92f49cfae..b696069562 100644
--- a/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp
+++ b/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp
@@ -12,7 +12,9 @@
//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "asm-printer"
+#include "ByteStreamer.h"
#include "llvm/CodeGen/AsmPrinter.h"
+#include "llvm/ADT/SmallBitVector.h"
#include "llvm/ADT/Twine.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/MC/MCAsmInfo.h"
@@ -52,9 +54,9 @@ void AsmPrinter::EmitULEB128(uint64_t Value, const char *Desc,
/// EmitCFAByte - Emit a .byte 42 directive for a DW_CFA_xxx value.
void AsmPrinter::EmitCFAByte(unsigned Val) const {
if (isVerbose()) {
- if (Val >= dwarf::DW_CFA_offset && Val < dwarf::DW_CFA_offset+64)
+ if (Val >= dwarf::DW_CFA_offset && Val < dwarf::DW_CFA_offset + 64)
OutStreamer.AddComment("DW_CFA_offset + Reg (" +
- Twine(Val-dwarf::DW_CFA_offset) + ")");
+ Twine(Val - dwarf::DW_CFA_offset) + ")");
else
OutStreamer.AddComment(dwarf::CallFrameString(Val));
}
@@ -63,43 +65,56 @@ void AsmPrinter::EmitCFAByte(unsigned Val) const {
static const char *DecodeDWARFEncoding(unsigned Encoding) {
switch (Encoding) {
- case dwarf::DW_EH_PE_absptr: return "absptr";
- case dwarf::DW_EH_PE_omit: return "omit";
- case dwarf::DW_EH_PE_pcrel: return "pcrel";
- case dwarf::DW_EH_PE_udata4: return "udata4";
- case dwarf::DW_EH_PE_udata8: return "udata8";
- case dwarf::DW_EH_PE_sdata4: return "sdata4";
- case dwarf::DW_EH_PE_sdata8: return "sdata8";
- case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_udata4: return "pcrel udata4";
- case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4: return "pcrel sdata4";
- case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_udata8: return "pcrel udata8";
- case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata8: return "pcrel sdata8";
- case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |dwarf::DW_EH_PE_udata4:
+ case dwarf::DW_EH_PE_absptr:
+ return "absptr";
+ case dwarf::DW_EH_PE_omit:
+ return "omit";
+ case dwarf::DW_EH_PE_pcrel:
+ return "pcrel";
+ case dwarf::DW_EH_PE_udata4:
+ return "udata4";
+ case dwarf::DW_EH_PE_udata8:
+ return "udata8";
+ case dwarf::DW_EH_PE_sdata4:
+ return "sdata4";
+ case dwarf::DW_EH_PE_sdata8:
+ return "sdata8";
+ case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_udata4:
+ return "pcrel udata4";
+ case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4:
+ return "pcrel sdata4";
+ case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_udata8:
+ return "pcrel udata8";
+ case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata8:
+ return "pcrel sdata8";
+ case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_udata4
+ :
return "indirect pcrel udata4";
- case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |dwarf::DW_EH_PE_sdata4:
+ case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4
+ :
return "indirect pcrel sdata4";
- case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |dwarf::DW_EH_PE_udata8:
+ case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_udata8
+ :
return "indirect pcrel udata8";
- case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |dwarf::DW_EH_PE_sdata8:
+ case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata8
+ :
return "indirect pcrel sdata8";
}
return "<unknown encoding>";
}
-
/// EmitEncodingByte - Emit a .byte 42 directive that corresponds to an
/// encoding. If verbose assembly output is enabled, we output comments
/// describing the encoding. Desc is an optional string saying what the
/// encoding is specifying (e.g. "LSDA").
void AsmPrinter::EmitEncodingByte(unsigned Val, const char *Desc) const {
if (isVerbose()) {
- if (Desc != 0)
- OutStreamer.AddComment(Twine(Desc)+" Encoding = " +
+ if (Desc)
+ OutStreamer.AddComment(Twine(Desc) + " Encoding = " +
Twine(DecodeDWARFEncoding(Val)));
else
- OutStreamer.AddComment(Twine("Encoding = ") +
- DecodeDWARFEncoding(Val));
+ OutStreamer.AddComment(Twine("Encoding = ") + DecodeDWARFEncoding(Val));
}
OutStreamer.EmitIntValue(Val, 1);
@@ -111,11 +126,16 @@ unsigned AsmPrinter::GetSizeOfEncodedValue(unsigned Encoding) const {
return 0;
switch (Encoding & 0x07) {
- default: llvm_unreachable("Invalid encoded value.");
- case dwarf::DW_EH_PE_absptr: return TM.getDataLayout()->getPointerSize();
- case dwarf::DW_EH_PE_udata2: return 2;
- case dwarf::DW_EH_PE_udata4: return 4;
- case dwarf::DW_EH_PE_udata8: return 8;
+ default:
+ llvm_unreachable("Invalid encoded value.");
+ case dwarf::DW_EH_PE_absptr:
+ return TM.getDataLayout()->getPointerSize();
+ case dwarf::DW_EH_PE_udata2:
+ return 2;
+ case dwarf::DW_EH_PE_udata4:
+ return 4;
+ case dwarf::DW_EH_PE_udata8:
+ return 8;
}
}
@@ -125,7 +145,7 @@ void AsmPrinter::EmitTTypeReference(const GlobalValue *GV,
const TargetLoweringObjectFile &TLOF = getObjFileLowering();
const MCExpr *Exp =
- TLOF.getTTypeGlobalReference(GV, Mang, MMI, Encoding, OutStreamer);
+ TLOF.getTTypeGlobalReference(GV, Encoding, *Mang, TM, MMI, OutStreamer);
OutStreamer.EmitValue(Exp, GetSizeOfEncodedValue(Encoding));
} else
OutStreamer.EmitIntValue(0, GetSizeOfEncodedValue(Encoding));
@@ -165,6 +185,150 @@ void AsmPrinter::EmitSectionOffset(const MCSymbol *Label,
EmitLabelDifference(Label, SectionLabel, 4);
}
+/// Emit a dwarf register operation.
+static void emitDwarfRegOp(ByteStreamer &Streamer, int Reg) {
+ assert(Reg >= 0);
+ if (Reg < 32) {
+ Streamer.EmitInt8(dwarf::DW_OP_reg0 + Reg,
+ dwarf::OperationEncodingString(dwarf::DW_OP_reg0 + Reg));
+ } else {
+ Streamer.EmitInt8(dwarf::DW_OP_regx, "DW_OP_regx");
+ Streamer.EmitULEB128(Reg, Twine(Reg));
+ }
+}
+
+/// Emit an (double-)indirect dwarf register operation.
+static void emitDwarfRegOpIndirect(ByteStreamer &Streamer, int Reg, int Offset,
+ bool Deref) {
+ assert(Reg >= 0);
+ if (Reg < 32) {
+ Streamer.EmitInt8(dwarf::DW_OP_breg0 + Reg,
+ dwarf::OperationEncodingString(dwarf::DW_OP_breg0 + Reg));
+ } else {
+ Streamer.EmitInt8(dwarf::DW_OP_bregx, "DW_OP_bregx");
+ Streamer.EmitULEB128(Reg, Twine(Reg));
+ }
+ Streamer.EmitSLEB128(Offset);
+ if (Deref)
+ Streamer.EmitInt8(dwarf::DW_OP_deref, "DW_OP_deref");
+}
+
+/// Emit a dwarf register operation for describing
+/// - a small value occupying only part of a register or
+/// - a small register representing only part of a value.
+static void emitDwarfOpPiece(ByteStreamer &Streamer, unsigned Size,
+ unsigned Offset) {
+ assert(Size > 0);
+ if (Offset > 0) {
+ Streamer.EmitInt8(dwarf::DW_OP_bit_piece, "DW_OP_bit_piece");
+ Streamer.EmitULEB128(Size, Twine(Size));
+ Streamer.EmitULEB128(Offset, Twine(Offset));
+ } else {
+ Streamer.EmitInt8(dwarf::DW_OP_piece, "DW_OP_piece");
+ unsigned ByteSize = Size / 8; // Assuming 8 bits per byte.
+ Streamer.EmitULEB128(ByteSize, Twine(ByteSize));
+ }
+}
+
+/// Some targets do not provide a DWARF register number for every
+/// register. This function attempts to emit a dwarf register by
+/// emitting a piece of a super-register or by piecing together
+/// multiple subregisters that alias the register.
+static void EmitDwarfRegOpPiece(ByteStreamer &Streamer, const AsmPrinter &AP,
+ const MachineLocation &MLoc) {
+ assert(!MLoc.isIndirect());
+ const TargetRegisterInfo *TRI = AP.TM.getRegisterInfo();
+ int Reg = TRI->getDwarfRegNum(MLoc.getReg(), false);
+
+ // Walk up the super-register chain until we find a valid number.
+ // For example, EAX on x86_64 is a 32-bit piece of RAX with offset 0.
+ for (MCSuperRegIterator SR(MLoc.getReg(), TRI); SR.isValid(); ++SR) {
+ Reg = TRI->getDwarfRegNum(*SR, false);
+ if (Reg >= 0) {
+ unsigned Idx = TRI->getSubRegIndex(*SR, MLoc.getReg());
+ unsigned Size = TRI->getSubRegIdxSize(Idx);
+ unsigned Offset = TRI->getSubRegIdxOffset(Idx);
+ AP.OutStreamer.AddComment("super-register");
+ emitDwarfRegOp(Streamer, Reg);
+ emitDwarfOpPiece(Streamer, Size, Offset);
+ return;
+ }
+ }
+
+ // Otherwise, attempt to find a covering set of sub-register numbers.
+ // For example, Q0 on ARM is a composition of D0+D1.
+ //
+ // Keep track of the current position so we can emit the more
+ // efficient DW_OP_piece.
+ unsigned CurPos = 0;
+ // The size of the register in bits, assuming 8 bits per byte.
+ unsigned RegSize = TRI->getMinimalPhysRegClass(MLoc.getReg())->getSize() * 8;
+ // Keep track of the bits in the register we already emitted, so we
+ // can avoid emitting redundant aliasing subregs.
+ SmallBitVector Coverage(RegSize, false);
+ for (MCSubRegIterator SR(MLoc.getReg(), TRI); SR.isValid(); ++SR) {
+ unsigned Idx = TRI->getSubRegIndex(MLoc.getReg(), *SR);
+ unsigned Size = TRI->getSubRegIdxSize(Idx);
+ unsigned Offset = TRI->getSubRegIdxOffset(Idx);
+ Reg = TRI->getDwarfRegNum(*SR, false);
+
+ // Intersection between the bits we already emitted and the bits
+ // covered by this subregister.
+ SmallBitVector Intersection(RegSize, false);
+ Intersection.set(Offset, Offset + Size);
+ Intersection ^= Coverage;
+
+ // If this sub-register has a DWARF number and we haven't covered
+ // its range, emit a DWARF piece for it.
+ if (Reg >= 0 && Intersection.any()) {
+ AP.OutStreamer.AddComment("sub-register");
+ emitDwarfRegOp(Streamer, Reg);
+ emitDwarfOpPiece(Streamer, Size, Offset == CurPos ? 0 : Offset);
+ CurPos = Offset + Size;
+
+ // Mark it as emitted.
+ Coverage.set(Offset, Offset + Size);
+ }
+ }
+
+ if (CurPos == 0) {
+ // FIXME: We have no reasonable way of handling errors in here.
+ Streamer.EmitInt8(dwarf::DW_OP_nop,
+ "nop (could not find a dwarf register number)");
+ }
+}
+
+/// EmitDwarfRegOp - Emit dwarf register operation.
+void AsmPrinter::EmitDwarfRegOp(ByteStreamer &Streamer,
+ const MachineLocation &MLoc,
+ bool Indirect) const {
+ const TargetRegisterInfo *TRI = TM.getRegisterInfo();
+ int Reg = TRI->getDwarfRegNum(MLoc.getReg(), false);
+ if (Reg < 0) {
+ // We assume that pointers are always in an addressable register.
+ if (Indirect || MLoc.isIndirect()) {
+ // FIXME: We have no reasonable way of handling errors in here. The
+ // caller might be in the middle of a dwarf expression. We should
+ // probably assert that Reg >= 0 once debug info generation is more
+ // mature.
+ Streamer.EmitInt8(dwarf::DW_OP_nop,
+ "nop (invalid dwarf register number for indirect loc)");
+ return;
+ }
+
+ // Attempt to find a valid super- or sub-register.
+ if (!Indirect && !MLoc.isIndirect())
+ return EmitDwarfRegOpPiece(Streamer, *this, MLoc);
+ }
+
+ if (MLoc.isIndirect())
+ emitDwarfRegOpIndirect(Streamer, Reg, MLoc.getOffset(), Indirect);
+ else if (Indirect)
+ emitDwarfRegOpIndirect(Streamer, Reg, 0, false);
+ else
+ emitDwarfRegOp(Streamer, Reg);
+}
+
//===----------------------------------------------------------------------===//
// Dwarf Lowering Routines
//===----------------------------------------------------------------------===//
@@ -191,5 +355,8 @@ void AsmPrinter::emitCFIInstruction(const MCCFIInstruction &Inst) const {
case MCCFIInstruction::OpWindowSave:
OutStreamer.EmitCFIWindowSave();
break;
+ case MCCFIInstruction::OpSameValue:
+ OutStreamer.EmitCFISameValue(Inst.getRegister());
+ break;
}
}
diff --git a/lib/CodeGen/AsmPrinter/AsmPrinterHandler.h b/lib/CodeGen/AsmPrinter/AsmPrinterHandler.h
new file mode 100644
index 0000000000..2825367abd
--- /dev/null
+++ b/lib/CodeGen/AsmPrinter/AsmPrinterHandler.h
@@ -0,0 +1,57 @@
+//===-- 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 CODEGEN_ASMPRINTER_ASMPRINTERHANDLER_H__
+#define CODEGEN_ASMPRINTER_ASMPRINTERHANDLER_H__
+
+#include "llvm/Support/DataTypes.h"
+
+namespace llvm {
+
+class MachineFunction;
+class MachineInstr;
+class MCSymbol;
+
+/// \brief Collects and handles AsmPrinter objects required to build debug
+/// or EH information.
+class AsmPrinterHandler {
+public:
+ virtual ~AsmPrinterHandler();
+
+ /// \brief For symbols that have a size designated (e.g. common symbols),
+ /// this tracks that size.
+ virtual void setSymbolSize(const MCSymbol *Sym, uint64_t Size) = 0;
+
+ /// \brief Emit all sections that should come after the content.
+ virtual void endModule() = 0;
+
+ /// \brief Gather pre-function debug information.
+ /// Every beginFunction(MF) call should be followed by an endFunction(MF)
+ /// call.
+ virtual void beginFunction(const MachineFunction *MF) = 0;
+
+ /// \brief Gather post-function debug information.
+ /// Please note that some AsmPrinter implementations may not call
+ /// beginFunction at all.
+ virtual void endFunction(const MachineFunction *MF) = 0;
+
+ /// \brief Process beginning of an instruction.
+ virtual void beginInstruction(const MachineInstr *MI) = 0;
+
+ /// \brief Process end of an instruction.
+ virtual void endInstruction() = 0;
+};
+} // End of namespace llvm
+
+#endif
diff --git a/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp b/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp
index 4f927f6ba8..567b6e3b18 100644
--- a/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp
+++ b/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp
@@ -13,12 +13,12 @@
#define DEBUG_TYPE "asm-printer"
#include "llvm/CodeGen/AsmPrinter.h"
-#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/Twine.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/IR/Constants.h"
+#include "llvm/IR/DataLayout.h"
#include "llvm/IR/InlineAsm.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
@@ -33,6 +33,7 @@
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetMachine.h"
+#include "llvm/Target/TargetSubtargetInfo.h"
using namespace llvm;
namespace {
@@ -77,11 +78,17 @@ void AsmPrinter::EmitInlineAsm(StringRef Str, const MDNode *LocMDNode,
if (isNullTerminated)
Str = Str.substr(0, Str.size()-1);
- // If the output streamer is actually a .s file, just emit the blob textually.
+ // If the output streamer does not have mature MC support or the integrated
+ // assembler has been disabled, just emit the blob textually.
+ // Otherwise parse the asm and emit it via MC support.
// This is useful in case the asm parser doesn't handle something but the
// system assembler does.
- if (OutStreamer.hasRawTextSupport()) {
+ const MCAsmInfo *MCAI = TM.getMCAsmInfo();
+ assert(MCAI && "No MCAsmInfo");
+ if (!MCAI->useIntegratedAssembler() &&
+ !OutStreamer.isIntegratedAssemblerRequired()) {
OutStreamer.EmitRawText(Str);
+ emitInlineAsmEnd(TM.getSubtarget<MCSubtargetInfo>(), 0);
return;
}
@@ -110,20 +117,25 @@ void AsmPrinter::EmitInlineAsm(StringRef Str, const MDNode *LocMDNode,
// Tell SrcMgr about this buffer, it takes ownership of the buffer.
SrcMgr.AddNewSourceBuffer(Buffer, SMLoc());
- OwningPtr<MCAsmParser> Parser(createMCAsmParser(SrcMgr,
- OutContext, OutStreamer,
- *MAI));
-
- // FIXME: It would be nice if we can avoid createing a new instance of
- // MCSubtargetInfo here given TargetSubtargetInfo is available. However,
- // we have to watch out for asm directives which can change subtarget
- // state. e.g. .code 16, .code 32.
- OwningPtr<MCSubtargetInfo>
- STI(TM.getTarget().createMCSubtargetInfo(TM.getTargetTriple(),
- TM.getTargetCPU(),
- TM.getTargetFeatureString()));
- OwningPtr<MCTargetAsmParser>
- TAP(TM.getTarget().createMCAsmParser(*STI, *Parser, *MII));
+ std::unique_ptr<MCAsmParser> Parser(
+ createMCAsmParser(SrcMgr, OutContext, OutStreamer, *MAI));
+
+ // Initialize the parser with a fresh subtarget info. It is better to use a
+ // new STI here because the parser may modify it and we do not want those
+ // modifications to persist after parsing the inlineasm. The modifications
+ // made by the parser will be seen by the code emitters because it passes
+ // the current STI down to the EncodeInstruction() method.
+ std::unique_ptr<MCSubtargetInfo> STI(TM.getTarget().createMCSubtargetInfo(
+ TM.getTargetTriple(), TM.getTargetCPU(), TM.getTargetFeatureString()));
+
+ // Preserve a copy of the original STI because the parser may modify it. For
+ // example, when switching between arm and thumb mode. If the target needs to
+ // emit code to return to the original state it can do so in
+ // emitInlineAsmEnd().
+ MCSubtargetInfo STIOrig = *STI;
+
+ std::unique_ptr<MCTargetAsmParser> TAP(
+ TM.getTarget().createMCAsmParser(*STI, *Parser, *MII));
if (!TAP)
report_fatal_error("Inline asm not supported by this streamer because"
" we don't have an asm parser for this target\n");
@@ -133,6 +145,7 @@ void AsmPrinter::EmitInlineAsm(StringRef Str, const MDNode *LocMDNode,
// Don't implicitly switch to the text section before the asm.
int Res = Parser->Run(/*NoInitialTextSection*/ true,
/*NoFinalize*/ true);
+ emitInlineAsmEnd(STIOrig, STI.get());
if (Res && !HasDiagHandler)
report_fatal_error("Error parsing inline asm\n");
}
@@ -427,21 +440,14 @@ void AsmPrinter::EmitInlineAsm(const MachineInstr *MI) const {
// If this asmstr is empty, just print the #APP/#NOAPP markers.
// These are useful to see where empty asm's wound up.
if (AsmStr[0] == 0) {
- // Don't emit the comments if writing to a .o file.
- if (!OutStreamer.hasRawTextSupport()) return;
-
- OutStreamer.EmitRawText(Twine("\t")+MAI->getCommentString()+
- MAI->getInlineAsmStart());
- OutStreamer.EmitRawText(Twine("\t")+MAI->getCommentString()+
- MAI->getInlineAsmEnd());
+ OutStreamer.emitRawComment(MAI->getInlineAsmStart());
+ OutStreamer.emitRawComment(MAI->getInlineAsmEnd());
return;
}
// Emit the #APP start marker. This has to happen even if verbose-asm isn't
- // enabled, so we use EmitRawText.
- if (OutStreamer.hasRawTextSupport())
- OutStreamer.EmitRawText(Twine("\t")+MAI->getCommentString()+
- MAI->getInlineAsmStart());
+ // enabled, so we use emitRawComment.
+ OutStreamer.emitRawComment(MAI->getInlineAsmStart());
// Get the !srcloc metadata node if we have it, and decode the loc cookie from
// it.
@@ -476,10 +482,8 @@ void AsmPrinter::EmitInlineAsm(const MachineInstr *MI) const {
EmitInlineAsm(OS.str(), LocMD, MI->getInlineAsmDialect());
// Emit the #NOAPP end marker. This has to happen even if verbose-asm isn't
- // enabled, so we use EmitRawText.
- if (OutStreamer.hasRawTextSupport())
- OutStreamer.EmitRawText(Twine("\t")+MAI->getCommentString()+
- MAI->getInlineAsmEnd());
+ // enabled, so we use emitRawComment.
+ OutStreamer.emitRawComment(MAI->getInlineAsmEnd());
}
@@ -491,8 +495,9 @@ void AsmPrinter::EmitInlineAsm(const MachineInstr *MI) const {
/// for their own strange codes.
void AsmPrinter::PrintSpecial(const MachineInstr *MI, raw_ostream &OS,
const char *Code) const {
+ const DataLayout *DL = TM.getDataLayout();
if (!strcmp(Code, "private")) {
- OS << MAI->getPrivateGlobalPrefix();
+ OS << DL->getPrivateGlobalPrefix();
} else if (!strcmp(Code, "comment")) {
OS << MAI->getCommentString();
} else if (!strcmp(Code, "uid")) {
@@ -551,3 +556,5 @@ bool AsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
return true;
}
+void AsmPrinter::emitInlineAsmEnd(const MCSubtargetInfo &StartInfo,
+ const MCSubtargetInfo *EndInfo) const {}
diff --git a/lib/CodeGen/AsmPrinter/ByteStreamer.h b/lib/CodeGen/AsmPrinter/ByteStreamer.h
new file mode 100644
index 0000000000..6c01d65cc1
--- /dev/null
+++ b/lib/CodeGen/AsmPrinter/ByteStreamer.h
@@ -0,0 +1,71 @@
+//===-- llvm/CodeGen/ByteStreamer.h - ByteStreamer class --------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains a class that can take bytes that would normally be
+// streamed via the AsmPrinter.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CODEGEN_BYTESTREAMER_H
+#define LLVM_CODEGEN_BYTESTREAMER_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/CodeGen/AsmPrinter.h"
+#include "llvm/MC/MCStreamer.h"
+#include "DIEHash.h"
+
+namespace llvm {
+class ByteStreamer {
+ public:
+ virtual ~ByteStreamer() {}
+
+ // For now we're just handling the calls we need for dwarf emission/hashing.
+ virtual void EmitInt8(uint8_t Byte, const Twine &Comment = "") = 0;
+ virtual void EmitSLEB128(uint64_t DWord, const Twine &Comment = "") = 0;
+ virtual void EmitULEB128(uint64_t DWord, const Twine &Comment = "") = 0;
+};
+
+class APByteStreamer : public ByteStreamer {
+private:
+ AsmPrinter &AP;
+
+public:
+ APByteStreamer(AsmPrinter &Asm) : AP(Asm) {}
+ void EmitInt8(uint8_t Byte, const Twine &Comment) override {
+ AP.OutStreamer.AddComment(Comment);
+ AP.EmitInt8(Byte);
+ }
+ void EmitSLEB128(uint64_t DWord, const Twine &Comment) override {
+ AP.OutStreamer.AddComment(Comment);
+ AP.EmitSLEB128(DWord);
+ }
+ void EmitULEB128(uint64_t DWord, const Twine &Comment) override {
+ AP.OutStreamer.AddComment(Comment);
+ AP.EmitULEB128(DWord);
+ }
+};
+
+class HashingByteStreamer : public ByteStreamer {
+ private:
+ DIEHash &Hash;
+ public:
+ HashingByteStreamer(DIEHash &H) : Hash(H) {}
+ void EmitInt8(uint8_t Byte, const Twine &Comment) override {
+ Hash.update(Byte);
+ }
+ void EmitSLEB128(uint64_t DWord, const Twine &Comment) override {
+ Hash.addSLEB128(DWord);
+ }
+ void EmitULEB128(uint64_t DWord, const Twine &Comment) override {
+ Hash.addULEB128(DWord);
+ }
+};
+}
+
+#endif
diff --git a/lib/CodeGen/AsmPrinter/CMakeLists.txt b/lib/CodeGen/AsmPrinter/CMakeLists.txt
index be484a6fc9..b3eddac191 100644
--- a/lib/CodeGen/AsmPrinter/CMakeLists.txt
+++ b/lib/CodeGen/AsmPrinter/CMakeLists.txt
@@ -7,12 +7,13 @@ add_llvm_library(LLVMAsmPrinter
DIEHash.cpp
DwarfAccelTable.cpp
DwarfCFIException.cpp
- DwarfCompileUnit.cpp
DwarfDebug.cpp
DwarfException.cpp
+ DwarfUnit.cpp
ErlangGCPrinter.cpp
OcamlGCPrinter.cpp
Win64Exception.cpp
+ WinCodeViewLineTables.cpp
)
add_dependencies(LLVMAsmPrinter intrinsics_gen)
diff --git a/lib/CodeGen/AsmPrinter/DIE.cpp b/lib/CodeGen/AsmPrinter/DIE.cpp
index 69444285f4..26e8f2da85 100644
--- a/lib/CodeGen/AsmPrinter/DIE.cpp
+++ b/lib/CodeGen/AsmPrinter/DIE.cpp
@@ -13,17 +13,18 @@
#include "DIE.h"
#include "DwarfDebug.h"
+#include "DwarfUnit.h"
#include "llvm/ADT/Twine.h"
#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSymbol.h"
-#include "llvm/Support/Allocator.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/FormattedStream.h"
+#include "llvm/Support/LEB128.h"
#include "llvm/Support/MD5.h"
using namespace llvm;
@@ -48,7 +49,7 @@ void DIEAbbrevData::Profile(FoldingSetNodeID &ID) const {
///
void DIEAbbrev::Profile(FoldingSetNodeID &ID) const {
ID.AddInteger(unsigned(Tag));
- ID.AddInteger(ChildrenFlag);
+ ID.AddInteger(unsigned(Children));
// For each attribute description.
for (unsigned i = 0, N = Data.size(); i < N; ++i)
@@ -62,7 +63,7 @@ void DIEAbbrev::Emit(AsmPrinter *AP) const {
AP->EmitULEB128(Tag, dwarf::TagString(Tag));
// Emit whether it has children DIEs.
- AP->EmitULEB128(ChildrenFlag, dwarf::ChildrenString(ChildrenFlag));
+ AP->EmitULEB128((unsigned)Children, dwarf::ChildrenString(Children));
// For each attribute description.
for (unsigned i = 0, N = Data.size(); i < N; ++i) {
@@ -89,7 +90,7 @@ void DIEAbbrev::print(raw_ostream &O) {
<< " "
<< dwarf::TagString(Tag)
<< " "
- << dwarf::ChildrenString(ChildrenFlag)
+ << dwarf::ChildrenString(Children)
<< '\n';
for (unsigned i = 0, N = Data.size(); i < N; ++i) {
@@ -112,27 +113,28 @@ DIE::~DIE() {
delete Children[i];
}
-/// Climb up the parent chain to get the compile unit DIE to which this DIE
+/// Climb up the parent chain to get the unit DIE to which this DIE
/// belongs.
-const DIE *DIE::getCompileUnit() const {
- const DIE *Cu = getCompileUnitOrNull();
+const DIE *DIE::getUnit() const {
+ const DIE *Cu = getUnitOrNull();
assert(Cu && "We should not have orphaned DIEs.");
return Cu;
}
-/// Climb up the parent chain to get the compile unit DIE this DIE belongs
+/// Climb up the parent chain to get the unit DIE this DIE belongs
/// to. Return NULL if DIE is not added to an owner yet.
-const DIE *DIE::getCompileUnitOrNull() const {
+const DIE *DIE::getUnitOrNull() const {
const DIE *p = this;
while (p) {
- if (p->getTag() == dwarf::DW_TAG_compile_unit)
+ if (p->getTag() == dwarf::DW_TAG_compile_unit ||
+ p->getTag() == dwarf::DW_TAG_type_unit)
return p;
p = p->getParent();
}
return NULL;
}
-DIEValue *DIE::findAttribute(uint16_t Attribute) {
+DIEValue *DIE::findAttribute(dwarf::Attribute Attribute) const {
const SmallVectorImpl<DIEValue *> &Values = getValues();
const DIEAbbrev &Abbrevs = getAbbrev();
@@ -159,7 +161,7 @@ void DIE::print(raw_ostream &O, unsigned IndentCount) const {
O << Indent
<< dwarf::TagString(Abbrev.getTag())
<< " "
- << dwarf::ChildrenString(Abbrev.getChildrenFlag()) << "\n";
+ << dwarf::ChildrenString(Abbrev.hasChildren()) << "\n";
} else {
O << "Size: " << Size << "\n";
}
@@ -215,8 +217,7 @@ void DIEInteger::EmitValue(AsmPrinter *Asm, dwarf::Form Form) const {
case dwarf::DW_FORM_flag_present:
// Emit something to keep the lines and comments in sync.
// FIXME: Is there a better way to do this?
- if (Asm->OutStreamer.hasRawTextSupport())
- Asm->OutStreamer.EmitRawText("");
+ Asm->OutStreamer.AddBlankLine();
return;
case dwarf::DW_FORM_flag: // Fall thru
case dwarf::DW_FORM_ref1: // Fall thru
@@ -227,6 +228,7 @@ void DIEInteger::EmitValue(AsmPrinter *Asm, dwarf::Form Form) const {
case dwarf::DW_FORM_ref4: // Fall thru
case dwarf::DW_FORM_data4: Size = 4; break;
case dwarf::DW_FORM_ref8: // Fall thru
+ case dwarf::DW_FORM_ref_sig8: // Fall thru
case dwarf::DW_FORM_data8: Size = 8; break;
case dwarf::DW_FORM_GNU_str_index: Asm->EmitULEB128(Integer); return;
case dwarf::DW_FORM_GNU_addr_index: Asm->EmitULEB128(Integer); return;
@@ -253,11 +255,12 @@ unsigned DIEInteger::SizeOf(AsmPrinter *AP, dwarf::Form Form) const {
case dwarf::DW_FORM_ref4: // Fall thru
case dwarf::DW_FORM_data4: return sizeof(int32_t);
case dwarf::DW_FORM_ref8: // Fall thru
+ case dwarf::DW_FORM_ref_sig8: // Fall thru
case dwarf::DW_FORM_data8: return sizeof(int64_t);
- case dwarf::DW_FORM_GNU_str_index: return MCAsmInfo::getULEB128Size(Integer);
- case dwarf::DW_FORM_GNU_addr_index: return MCAsmInfo::getULEB128Size(Integer);
- case dwarf::DW_FORM_udata: return MCAsmInfo::getULEB128Size(Integer);
- case dwarf::DW_FORM_sdata: return MCAsmInfo::getSLEB128Size(Integer);
+ case dwarf::DW_FORM_GNU_str_index: return getULEB128Size(Integer);
+ case dwarf::DW_FORM_GNU_addr_index: return getULEB128Size(Integer);
+ case dwarf::DW_FORM_udata: return getULEB128Size(Integer);
+ case dwarf::DW_FORM_sdata: return getSLEB128Size(Integer);
case dwarf::DW_FORM_addr: return AP->getDataLayout().getPointerSize();
default: llvm_unreachable("DIE Value form not supported yet");
}
@@ -338,6 +341,7 @@ void DIEDelta::EmitValue(AsmPrinter *AP, dwarf::Form Form) const {
///
unsigned DIEDelta::SizeOf(AsmPrinter *AP, dwarf::Form Form) const {
if (Form == dwarf::DW_FORM_data4) return 4;
+ if (Form == dwarf::DW_FORM_sec_offset) return 4;
if (Form == dwarf::DW_FORM_strp) return 4;
return AP->getDataLayout().getPointerSize();
}
@@ -378,7 +382,26 @@ void DIEString::print(raw_ostream &O) const {
/// EmitValue - Emit debug information entry offset.
///
void DIEEntry::EmitValue(AsmPrinter *AP, dwarf::Form Form) const {
- AP->EmitInt32(Entry->getOffset());
+
+ if (Form == dwarf::DW_FORM_ref_addr) {
+ const DwarfDebug *DD = AP->getDwarfDebug();
+ unsigned Addr = Entry->getOffset();
+ assert(!DD->useSplitDwarf() && "TODO: dwo files can't have relocations.");
+ // For DW_FORM_ref_addr, output the offset from beginning of debug info
+ // section. Entry->getOffset() returns the offset from start of the
+ // compile unit.
+ DwarfCompileUnit *CU = DD->lookupUnit(Entry->getUnit());
+ assert(CU && "CUDie should belong to a CU.");
+ Addr += CU->getDebugInfoOffset();
+ if (AP->MAI->doesDwarfUseRelocationsAcrossSections())
+ AP->EmitLabelPlusOffset(CU->getSectionSym(), Addr,
+ DIEEntry::getRefAddrSize(AP));
+ else
+ AP->EmitLabelOffsetDifference(CU->getSectionSym(), Addr,
+ CU->getSectionSym(),
+ DIEEntry::getRefAddrSize(AP));
+ } else
+ AP->EmitInt32(Entry->getOffset());
}
unsigned DIEEntry::getRefAddrSize(AsmPrinter *AP) {
@@ -386,7 +409,9 @@ unsigned DIEEntry::getRefAddrSize(AsmPrinter *AP) {
// specified to be four bytes in the DWARF 32-bit format and eight bytes
// in the DWARF 64-bit format, while DWARF Version 2 specifies that such
// references have the same size as an address on the target system.
- if (AP->getDwarfDebug()->getDwarfVersion() == 2)
+ const DwarfDebug *DD = AP->getDwarfDebug();
+ assert(DD && "Expected Dwarf Debug info to be available");
+ if (DD->getDwarfVersion() == 2)
return AP->getDataLayout().getPointerSize();
return sizeof(int32_t);
}
@@ -398,12 +423,83 @@ void DIEEntry::print(raw_ostream &O) const {
#endif
//===----------------------------------------------------------------------===//
+// DIETypeSignature Implementation
+//===----------------------------------------------------------------------===//
+void DIETypeSignature::EmitValue(AsmPrinter *Asm, dwarf::Form Form) const {
+ assert(Form == dwarf::DW_FORM_ref_sig8);
+ Asm->OutStreamer.EmitIntValue(Unit.getTypeSignature(), 8);
+}
+
+#ifndef NDEBUG
+void DIETypeSignature::print(raw_ostream &O) const {
+ O << format("Type Unit: 0x%lx", Unit.getTypeSignature());
+}
+
+void DIETypeSignature::dump() const { print(dbgs()); }
+#endif
+
+//===----------------------------------------------------------------------===//
+// DIELoc Implementation
+//===----------------------------------------------------------------------===//
+
+/// ComputeSize - calculate the size of the location expression.
+///
+unsigned DIELoc::ComputeSize(AsmPrinter *AP) const {
+ if (!Size) {
+ const SmallVectorImpl<DIEAbbrevData> &AbbrevData = Abbrev.getData();
+ for (unsigned i = 0, N = Values.size(); i < N; ++i)
+ Size += Values[i]->SizeOf(AP, AbbrevData[i].getForm());
+ }
+
+ return Size;
+}
+
+/// EmitValue - Emit location data.
+///
+void DIELoc::EmitValue(AsmPrinter *Asm, dwarf::Form Form) const {
+ switch (Form) {
+ default: llvm_unreachable("Improper form for block");
+ case dwarf::DW_FORM_block1: Asm->EmitInt8(Size); break;
+ case dwarf::DW_FORM_block2: Asm->EmitInt16(Size); break;
+ case dwarf::DW_FORM_block4: Asm->EmitInt32(Size); break;
+ case dwarf::DW_FORM_block:
+ case dwarf::DW_FORM_exprloc:
+ Asm->EmitULEB128(Size); break;
+ }
+
+ const SmallVectorImpl<DIEAbbrevData> &AbbrevData = Abbrev.getData();
+ for (unsigned i = 0, N = Values.size(); i < N; ++i)
+ Values[i]->EmitValue(Asm, AbbrevData[i].getForm());
+}
+
+/// SizeOf - Determine size of location data in bytes.
+///
+unsigned DIELoc::SizeOf(AsmPrinter *AP, dwarf::Form Form) const {
+ switch (Form) {
+ case dwarf::DW_FORM_block1: return Size + sizeof(int8_t);
+ case dwarf::DW_FORM_block2: return Size + sizeof(int16_t);
+ case dwarf::DW_FORM_block4: return Size + sizeof(int32_t);
+ case dwarf::DW_FORM_block:
+ case dwarf::DW_FORM_exprloc:
+ return Size + getULEB128Size(Size);
+ default: llvm_unreachable("Improper form for block");
+ }
+}
+
+#ifndef NDEBUG
+void DIELoc::print(raw_ostream &O) const {
+ O << "ExprLoc: ";
+ DIE::print(O, 5);
+}
+#endif
+
+//===----------------------------------------------------------------------===//
// DIEBlock Implementation
//===----------------------------------------------------------------------===//
/// ComputeSize - calculate the size of the block.
///
-unsigned DIEBlock::ComputeSize(AsmPrinter *AP) {
+unsigned DIEBlock::ComputeSize(AsmPrinter *AP) const {
if (!Size) {
const SmallVectorImpl<DIEAbbrevData> &AbbrevData = Abbrev.getData();
for (unsigned i = 0, N = Values.size(); i < N; ++i)
@@ -436,7 +532,7 @@ unsigned DIEBlock::SizeOf(AsmPrinter *AP, dwarf::Form Form) const {
case dwarf::DW_FORM_block1: return Size + sizeof(int8_t);
case dwarf::DW_FORM_block2: return Size + sizeof(int16_t);
case dwarf::DW_FORM_block4: return Size + sizeof(int32_t);
- case dwarf::DW_FORM_block: return Size + MCAsmInfo::getULEB128Size(Size);
+ case dwarf::DW_FORM_block: return Size + getULEB128Size(Size);
default: llvm_unreachable("Improper form for block");
}
}
@@ -447,3 +543,34 @@ void DIEBlock::print(raw_ostream &O) const {
DIE::print(O, 5);
}
#endif
+
+//===----------------------------------------------------------------------===//
+// DIELocList Implementation
+//===----------------------------------------------------------------------===//
+
+unsigned DIELocList::SizeOf(AsmPrinter *AP, dwarf::Form Form) const {
+ if (Form == dwarf::DW_FORM_data4)
+ return 4;
+ if (Form == dwarf::DW_FORM_sec_offset)
+ return 4;
+ return AP->getDataLayout().getPointerSize();
+}
+
+/// EmitValue - Emit label value.
+///
+void DIELocList::EmitValue(AsmPrinter *AP, dwarf::Form Form) const {
+ DwarfDebug *DD = AP->getDwarfDebug();
+ MCSymbol *Label = DD->getDebugLocEntries()[Index].Label;
+
+ if (AP->MAI->doesDwarfUseRelocationsAcrossSections() && !DD->useSplitDwarf())
+ AP->EmitSectionOffset(Label, DD->getDebugLocSym());
+ else
+ AP->EmitLabelDifference(Label, DD->getDebugLocSym(), 4);
+}
+
+#ifndef NDEBUG
+void DIELocList::print(raw_ostream &O) const {
+ O << "LocList: " << Index;
+
+}
+#endif
diff --git a/lib/CodeGen/AsmPrinter/DIE.h b/lib/CodeGen/AsmPrinter/DIE.h
index f4fa326ef6..7fefd4f4cb 100644
--- a/lib/CodeGen/AsmPrinter/DIE.h
+++ b/lib/CodeGen/AsmPrinter/DIE.h
@@ -16,437 +16,560 @@
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/SmallVector.h"
-#include "llvm/Support/Compiler.h"
#include "llvm/Support/Dwarf.h"
-#include "llvm/MC/MCExpr.h"
#include <vector>
namespace llvm {
- class AsmPrinter;
- class MCSymbol;
- class MCSymbolRefExpr;
- class raw_ostream;
-
- //===--------------------------------------------------------------------===//
- /// DIEAbbrevData - Dwarf abbreviation data, describes one attribute of a
- /// Dwarf abbreviation.
- class DIEAbbrevData {
- /// Attribute - Dwarf attribute code.
- ///
- dwarf::Attribute Attribute;
-
- /// Form - Dwarf form code.
- ///
- dwarf::Form Form;
- public:
- DIEAbbrevData(dwarf::Attribute A, dwarf::Form F) : Attribute(A), Form(F) {}
-
- // Accessors.
- dwarf::Attribute getAttribute() const { return Attribute; }
- dwarf::Form getForm() const { return Form; }
-
- /// Profile - Used to gather unique data for the abbreviation folding set.
- ///
- void Profile(FoldingSetNodeID &ID) const;
- };
+class AsmPrinter;
+class MCExpr;
+class MCSymbol;
+class raw_ostream;
+class DwarfTypeUnit;
+
+//===--------------------------------------------------------------------===//
+/// DIEAbbrevData - Dwarf abbreviation data, describes one attribute of a
+/// Dwarf abbreviation.
+class DIEAbbrevData {
+ /// Attribute - Dwarf attribute code.
+ ///
+ dwarf::Attribute Attribute;
- //===--------------------------------------------------------------------===//
- /// DIEAbbrev - Dwarf abbreviation, describes the organization of a debug
- /// information object.
- class DIEAbbrev : public FoldingSetNode {
- /// Tag - Dwarf tag code.
- ///
- dwarf::Tag Tag;
-
- /// ChildrenFlag - Dwarf children flag.
- ///
- uint16_t ChildrenFlag;
-
- /// Unique number for node.
- ///
- unsigned Number;
-
- /// Data - Raw data bytes for abbreviation.
- ///
- SmallVector<DIEAbbrevData, 12> Data;
-
- public:
- DIEAbbrev(dwarf::Tag T, uint16_t C) : Tag(T), ChildrenFlag(C), Data() {}
-
- // Accessors.
- dwarf::Tag getTag() const { return Tag; }
- unsigned getNumber() const { return Number; }
- uint16_t getChildrenFlag() const { return ChildrenFlag; }
- const SmallVectorImpl<DIEAbbrevData> &getData() const { return Data; }
- void setChildrenFlag(uint16_t CF) { ChildrenFlag = CF; }
- void setNumber(unsigned N) { Number = N; }
-
- /// AddAttribute - Adds another set of attribute information to the
- /// abbreviation.
- void AddAttribute(dwarf::Attribute Attribute, dwarf::Form Form) {
- Data.push_back(DIEAbbrevData(Attribute, Form));
- }
+ /// Form - Dwarf form code.
+ ///
+ dwarf::Form Form;
+
+public:
+ DIEAbbrevData(dwarf::Attribute A, dwarf::Form F) : Attribute(A), Form(F) {}
+
+ // Accessors.
+ dwarf::Attribute getAttribute() const { return Attribute; }
+ dwarf::Form getForm() const { return Form; }
+
+ /// Profile - Used to gather unique data for the abbreviation folding set.
+ ///
+ void Profile(FoldingSetNodeID &ID) const;
+};
+
+//===--------------------------------------------------------------------===//
+/// DIEAbbrev - Dwarf abbreviation, describes the organization of a debug
+/// information object.
+class DIEAbbrev : public FoldingSetNode {
+ /// Unique number for node.
+ ///
+ unsigned Number;
- /// Profile - Used to gather unique data for the abbreviation folding set.
- ///
- void Profile(FoldingSetNodeID &ID) const;
+ /// Tag - Dwarf tag code.
+ ///
+ dwarf::Tag Tag;
- /// Emit - Print the abbreviation using the specified asm printer.
- ///
- void Emit(AsmPrinter *AP) const;
+ /// Children - Whether or not this node has children.
+ ///
+ // This cheats a bit in all of the uses since the values in the standard
+ // are 0 and 1 for no children and children respectively.
+ bool Children;
+
+ /// Data - Raw data bytes for abbreviation.
+ ///
+ SmallVector<DIEAbbrevData, 12> Data;
+
+public:
+ DIEAbbrev(dwarf::Tag T, bool C) : Tag(T), Children(C), Data() {}
+
+ // Accessors.
+ dwarf::Tag getTag() const { return Tag; }
+ unsigned getNumber() const { return Number; }
+ bool hasChildren() const { return Children; }
+ const SmallVectorImpl<DIEAbbrevData> &getData() const { return Data; }
+ void setChildrenFlag(bool hasChild) { Children = hasChild; }
+ void setNumber(unsigned N) { Number = N; }
+
+ /// AddAttribute - Adds another set of attribute information to the
+ /// abbreviation.
+ void AddAttribute(dwarf::Attribute Attribute, dwarf::Form Form) {
+ Data.push_back(DIEAbbrevData(Attribute, Form));
+ }
+
+ /// Profile - Used to gather unique data for the abbreviation folding set.
+ ///
+ void Profile(FoldingSetNodeID &ID) const;
+
+ /// Emit - Print the abbreviation using the specified asm printer.
+ ///
+ void Emit(AsmPrinter *AP) const;
#ifndef NDEBUG
- void print(raw_ostream &O);
- void dump();
+ void print(raw_ostream &O);
+ void dump();
#endif
- };
+};
- //===--------------------------------------------------------------------===//
- /// DIE - A structured debug information entry. Has an abbreviation which
- /// describes its organization.
- class DIEValue;
-
- class DIE {
- protected:
- /// Offset - Offset in debug info section.
- ///
- unsigned Offset;
-
- /// Size - Size of instance + children.
- ///
- unsigned Size;
-
- /// Abbrev - Buffer for constructing abbreviation.
- ///
- DIEAbbrev Abbrev;
-
- /// Children DIEs.
- ///
- std::vector<DIE *> Children;
-
- DIE *Parent;
-
- /// Attribute values.
- ///
- SmallVector<DIEValue*, 12> Values;
-
- public:
- explicit DIE(unsigned Tag)
- : Offset(0), Size(0), Abbrev((dwarf::Tag)Tag, dwarf::DW_CHILDREN_no),
- Parent(0) {}
- virtual ~DIE();
-
- // Accessors.
- DIEAbbrev &getAbbrev() { return Abbrev; }
- const DIEAbbrev &getAbbrev() const { return Abbrev; }
- unsigned getAbbrevNumber() const { return Abbrev.getNumber(); }
- dwarf::Tag getTag() const { return Abbrev.getTag(); }
- unsigned getOffset() const { return Offset; }
- unsigned getSize() const { return Size; }
- const std::vector<DIE *> &getChildren() const { return Children; }
- const SmallVectorImpl<DIEValue*> &getValues() const { return Values; }
- DIE *getParent() const { return Parent; }
- /// Climb up the parent chain to get the compile unit DIE this DIE belongs
- /// to.
- const DIE *getCompileUnit() const;
- /// Similar to getCompileUnit, returns null when DIE is not added to an
- /// owner yet.
- const DIE *getCompileUnitOrNull() const;
- void setOffset(unsigned O) { Offset = O; }
- void setSize(unsigned S) { Size = S; }
-
- /// addValue - Add a value and attributes to a DIE.
- ///
- void addValue(dwarf::Attribute Attribute, dwarf::Form Form,
- DIEValue *Value) {
- Abbrev.AddAttribute(Attribute, Form);
- Values.push_back(Value);
- }
+//===--------------------------------------------------------------------===//
+/// DIE - A structured debug information entry. Has an abbreviation which
+/// describes its organization.
+class DIEValue;
- /// addChild - Add a child to the DIE.
- ///
- void addChild(DIE *Child) {
- assert(!Child->getParent());
- Abbrev.setChildrenFlag(dwarf::DW_CHILDREN_yes);
- Children.push_back(Child);
- Child->Parent = this;
- }
+class DIE {
+protected:
+ /// Offset - Offset in debug info section.
+ ///
+ unsigned Offset;
+
+ /// Size - Size of instance + children.
+ ///
+ unsigned Size;
+
+ /// Abbrev - Buffer for constructing abbreviation.
+ ///
+ DIEAbbrev Abbrev;
+
+ /// Children DIEs.
+ ///
+ std::vector<DIE *> Children;
+
+ DIE *Parent;
- /// findAttribute - Find a value in the DIE with the attribute given, returns NULL
- /// if no such attribute exists.
- DIEValue *findAttribute(uint16_t Attribute);
+ /// Attribute values.
+ ///
+ SmallVector<DIEValue *, 12> Values;
+
+public:
+ explicit DIE(unsigned Tag)
+ : Offset(0), Size(0), Abbrev((dwarf::Tag)Tag, dwarf::DW_CHILDREN_no),
+ Parent(0) {}
+ ~DIE();
+
+ // Accessors.
+ DIEAbbrev &getAbbrev() { return Abbrev; }
+ const DIEAbbrev &getAbbrev() const { return Abbrev; }
+ unsigned getAbbrevNumber() const { return Abbrev.getNumber(); }
+ dwarf::Tag getTag() const { return Abbrev.getTag(); }
+ unsigned getOffset() const { return Offset; }
+ unsigned getSize() const { return Size; }
+ const std::vector<DIE *> &getChildren() const { return Children; }
+ const SmallVectorImpl<DIEValue *> &getValues() const { return Values; }
+ DIE *getParent() const { return Parent; }
+ /// Climb up the parent chain to get the compile or type unit DIE this DIE
+ /// belongs to.
+ const DIE *getUnit() const;
+ /// Similar to getUnit, returns null when DIE is not added to an
+ /// owner yet.
+ const DIE *getUnitOrNull() const;
+ void setOffset(unsigned O) { Offset = O; }
+ void setSize(unsigned S) { Size = S; }
+
+ /// addValue - Add a value and attributes to a DIE.
+ ///
+ void addValue(dwarf::Attribute Attribute, dwarf::Form Form, DIEValue *Value) {
+ Abbrev.AddAttribute(Attribute, Form);
+ Values.push_back(Value);
+ }
+
+ /// addChild - Add a child to the DIE.
+ ///
+ void addChild(DIE *Child) {
+ assert(!Child->getParent());
+ Abbrev.setChildrenFlag(dwarf::DW_CHILDREN_yes);
+ Children.push_back(Child);
+ Child->Parent = this;
+ }
+
+ /// findAttribute - Find a value in the DIE with the attribute given,
+ /// returns NULL if no such attribute exists.
+ DIEValue *findAttribute(dwarf::Attribute Attribute) const;
#ifndef NDEBUG
- void print(raw_ostream &O, unsigned IndentCount = 0) const;
- void dump();
+ void print(raw_ostream &O, unsigned IndentCount = 0) const;
+ void dump();
#endif
+};
+
+//===--------------------------------------------------------------------===//
+/// DIEValue - A debug information entry value. Some of these roughly correlate
+/// to DWARF attribute classes.
+///
+class DIEValue {
+ virtual void anchor();
+
+public:
+ enum Type {
+ isInteger,
+ isString,
+ isExpr,
+ isLabel,
+ isDelta,
+ isEntry,
+ isTypeSignature,
+ isBlock,
+ isLoc,
+ isLocList,
};
- //===--------------------------------------------------------------------===//
- /// DIEValue - A debug information entry value.
- ///
- class DIEValue {
- virtual void anchor();
- public:
- enum {
- isInteger,
- isString,
- isExpr,
- isLabel,
- isDelta,
- isEntry,
- isBlock
- };
- protected:
- /// Type - Type of data stored in the value.
- ///
- unsigned Type;
- public:
- explicit DIEValue(unsigned T) : Type(T) {}
- virtual ~DIEValue() {}
-
- // Accessors
- unsigned getType() const { return Type; }
-
- /// EmitValue - Emit value via the Dwarf writer.
- ///
- virtual void EmitValue(AsmPrinter *AP, dwarf::Form Form) const = 0;
-
- /// SizeOf - Return the size of a value in bytes.
- ///
- virtual unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const = 0;
+protected:
+ /// Ty - Type of data stored in the value.
+ ///
+ Type Ty;
+
+ explicit DIEValue(Type T) : Ty(T) {}
+ virtual ~DIEValue() {}
+
+public:
+ // Accessors
+ Type getType() const { return Ty; }
+
+ /// EmitValue - Emit value via the Dwarf writer.
+ ///
+ virtual void EmitValue(AsmPrinter *AP, dwarf::Form Form) const = 0;
+
+ /// SizeOf - Return the size of a value in bytes.
+ ///
+ virtual unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const = 0;
#ifndef NDEBUG
- virtual void print(raw_ostream &O) const = 0;
- void dump() const;
+ virtual void print(raw_ostream &O) const = 0;
+ void dump() const;
#endif
- };
+};
+
+//===--------------------------------------------------------------------===//
+/// DIEInteger - An integer value DIE.
+///
+class DIEInteger : public DIEValue {
+ uint64_t Integer;
- //===--------------------------------------------------------------------===//
- /// DIEInteger - An integer value DIE.
- ///
- class DIEInteger : public DIEValue {
- uint64_t Integer;
- public:
- explicit DIEInteger(uint64_t I) : DIEValue(isInteger), Integer(I) {}
-
- /// BestForm - Choose the best form for integer.
- ///
- static dwarf::Form BestForm(bool IsSigned, uint64_t Int) {
- if (IsSigned) {
- const int64_t SignedInt = Int;
- if ((char)Int == SignedInt) return dwarf::DW_FORM_data1;
- if ((short)Int == SignedInt) return dwarf::DW_FORM_data2;
- if ((int)Int == SignedInt) return dwarf::DW_FORM_data4;
- } else {
- if ((unsigned char)Int == Int) return dwarf::DW_FORM_data1;
- if ((unsigned short)Int == Int) return dwarf::DW_FORM_data2;
- if ((unsigned int)Int == Int) return dwarf::DW_FORM_data4;
- }
- return dwarf::DW_FORM_data8;
+public:
+ explicit DIEInteger(uint64_t I) : DIEValue(isInteger), Integer(I) {}
+
+ /// BestForm - Choose the best form for integer.
+ ///
+ static dwarf::Form BestForm(bool IsSigned, uint64_t Int) {
+ if (IsSigned) {
+ const int64_t SignedInt = Int;
+ if ((char)Int == SignedInt)
+ return dwarf::DW_FORM_data1;
+ if ((short)Int == SignedInt)
+ return dwarf::DW_FORM_data2;
+ if ((int)Int == SignedInt)
+ return dwarf::DW_FORM_data4;
+ } else {
+ if ((unsigned char)Int == Int)
+ return dwarf::DW_FORM_data1;
+ if ((unsigned short)Int == Int)
+ return dwarf::DW_FORM_data2;
+ if ((unsigned int)Int == Int)
+ return dwarf::DW_FORM_data4;
}
+ return dwarf::DW_FORM_data8;
+ }
- /// EmitValue - Emit integer of appropriate size.
- ///
- virtual void EmitValue(AsmPrinter *AP, dwarf::Form Form) const;
+ /// EmitValue - Emit integer of appropriate size.
+ ///
+ void EmitValue(AsmPrinter *AP, dwarf::Form Form) const override;
- uint64_t getValue() const { return Integer; }
+ uint64_t getValue() const { return Integer; }
- /// SizeOf - Determine size of integer value in bytes.
- ///
- virtual unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const;
+ /// SizeOf - Determine size of integer value in bytes.
+ ///
+ unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const override;
- // Implement isa/cast/dyncast.
- static bool classof(const DIEValue *I) { return I->getType() == isInteger; }
+ // Implement isa/cast/dyncast.
+ static bool classof(const DIEValue *I) { return I->getType() == isInteger; }
#ifndef NDEBUG
- virtual void print(raw_ostream &O) const;
+ void print(raw_ostream &O) const override;
#endif
- };
+};
- //===--------------------------------------------------------------------===//
- /// DIEExpr - An expression DIE.
- //
- class DIEExpr : public DIEValue {
- const MCExpr *Expr;
- public:
- explicit DIEExpr(const MCExpr *E) : DIEValue(isExpr), Expr(E) {}
+//===--------------------------------------------------------------------===//
+/// DIEExpr - An expression DIE.
+//
+class DIEExpr : public DIEValue {
+ const MCExpr *Expr;
- /// EmitValue - Emit expression value.
- ///
- virtual void EmitValue(AsmPrinter *AP, dwarf::Form Form) const;
+public:
+ explicit DIEExpr(const MCExpr *E) : DIEValue(isExpr), Expr(E) {}
- /// getValue - Get MCExpr.
- ///
- const MCExpr *getValue() const { return Expr; }
+ /// EmitValue - Emit expression value.
+ ///
+ void EmitValue(AsmPrinter *AP, dwarf::Form Form) const override;
- /// SizeOf - Determine size of expression value in bytes.
- ///
- virtual unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const;
+ /// getValue - Get MCExpr.
+ ///
+ const MCExpr *getValue() const { return Expr; }
+
+ /// SizeOf - Determine size of expression value in bytes.
+ ///
+ unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const override;
- // Implement isa/cast/dyncast.
- static bool classof(const DIEValue *E) { return E->getType() == isExpr; }
+ // Implement isa/cast/dyncast.
+ static bool classof(const DIEValue *E) { return E->getType() == isExpr; }
#ifndef NDEBUG
- virtual void print(raw_ostream &O) const;
+ void print(raw_ostream &O) const override;
#endif
- };
+};
+
+//===--------------------------------------------------------------------===//
+/// DIELabel - A label DIE.
+//
+class DIELabel : public DIEValue {
+ const MCSymbol *Label;
- //===--------------------------------------------------------------------===//
- /// DIELabel - A label DIE.
- //
- class DIELabel : public DIEValue {
- const MCSymbol *Label;
- public:
- explicit DIELabel(const MCSymbol *L) : DIEValue(isLabel), Label(L) {}
+public:
+ explicit DIELabel(const MCSymbol *L) : DIEValue(isLabel), Label(L) {}
- /// EmitValue - Emit label value.
- ///
- virtual void EmitValue(AsmPrinter *AP, dwarf::Form Form) const;
+ /// EmitValue - Emit label value.
+ ///
+ void EmitValue(AsmPrinter *AP, dwarf::Form Form) const override;
- /// getValue - Get MCSymbol.
- ///
- const MCSymbol *getValue() const { return Label; }
+ /// getValue - Get MCSymbol.
+ ///
+ const MCSymbol *getValue() const { return Label; }
- /// SizeOf - Determine size of label value in bytes.
- ///
- virtual unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const;
+ /// SizeOf - Determine size of label value in bytes.
+ ///
+ unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const override;
- // Implement isa/cast/dyncast.
- static bool classof(const DIEValue *L) { return L->getType() == isLabel; }
+ // Implement isa/cast/dyncast.
+ static bool classof(const DIEValue *L) { return L->getType() == isLabel; }
#ifndef NDEBUG
- virtual void print(raw_ostream &O) const;
+ void print(raw_ostream &O) const override;
#endif
- };
+};
- //===--------------------------------------------------------------------===//
- /// DIEDelta - A simple label difference DIE.
- ///
- class DIEDelta : public DIEValue {
- const MCSymbol *LabelHi;
- const MCSymbol *LabelLo;
- public:
- DIEDelta(const MCSymbol *Hi, const MCSymbol *Lo)
+//===--------------------------------------------------------------------===//
+/// DIEDelta - A simple label difference DIE.
+///
+class DIEDelta : public DIEValue {
+ const MCSymbol *LabelHi;
+ const MCSymbol *LabelLo;
+
+public:
+ DIEDelta(const MCSymbol *Hi, const MCSymbol *Lo)
: DIEValue(isDelta), LabelHi(Hi), LabelLo(Lo) {}
- /// EmitValue - Emit delta value.
- ///
- virtual void EmitValue(AsmPrinter *AP, dwarf::Form Form) const;
+ /// EmitValue - Emit delta value.
+ ///
+ void EmitValue(AsmPrinter *AP, dwarf::Form Form) const override;
- /// SizeOf - Determine size of delta value in bytes.
- ///
- virtual unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const;
+ /// SizeOf - Determine size of delta value in bytes.
+ ///
+ unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const override;
- // Implement isa/cast/dyncast.
- static bool classof(const DIEValue *D) { return D->getType() == isDelta; }
+ // Implement isa/cast/dyncast.
+ static bool classof(const DIEValue *D) { return D->getType() == isDelta; }
#ifndef NDEBUG
- virtual void print(raw_ostream &O) const;
+ void print(raw_ostream &O) const override;
#endif
- };
+};
+
+//===--------------------------------------------------------------------===//
+/// DIEString - A container for string values.
+///
+class DIEString : public DIEValue {
+ const DIEValue *Access;
+ const StringRef Str;
+
+public:
+ DIEString(const DIEValue *Acc, const StringRef S)
+ : DIEValue(isString), Access(Acc), Str(S) {}
- //===--------------------------------------------------------------------===//
- /// DIEString - A container for string values.
+ /// getString - Grab the string out of the object.
+ StringRef getString() const { return Str; }
+
+ /// EmitValue - Emit delta value.
///
- class DIEString : public DIEValue {
- const DIEValue *Access;
- const StringRef Str;
+ void EmitValue(AsmPrinter *AP, dwarf::Form Form) const override;
- public:
- DIEString(const DIEValue *Acc, const StringRef S)
- : DIEValue(isString), Access(Acc), Str(S) {}
+ /// SizeOf - Determine size of delta value in bytes.
+ ///
+ unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const override;
- /// getString - Grab the string out of the object.
- StringRef getString() const { return Str; }
+ // Implement isa/cast/dyncast.
+ static bool classof(const DIEValue *D) { return D->getType() == isString; }
- /// EmitValue - Emit delta value.
- ///
- virtual void EmitValue(AsmPrinter *AP, dwarf::Form Form) const;
+#ifndef NDEBUG
+ void print(raw_ostream &O) const override;
+#endif
+};
- /// SizeOf - Determine size of delta value in bytes.
- ///
- virtual unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const;
+//===--------------------------------------------------------------------===//
+/// DIEEntry - A pointer to another debug information entry. An instance of
+/// this class can also be used as a proxy for a debug information entry not
+/// yet defined (ie. types.)
+class DIEEntry : public DIEValue {
+ DIE *const Entry;
- // Implement isa/cast/dyncast.
- static bool classof(const DIEValue *D) { return D->getType() == isString; }
+public:
+ explicit DIEEntry(DIE *E) : DIEValue(isEntry), Entry(E) {
+ assert(E && "Cannot construct a DIEEntry with a null DIE");
+ }
- #ifndef NDEBUG
- virtual void print(raw_ostream &O) const;
- #endif
- };
+ DIE *getEntry() const { return Entry; }
- //===--------------------------------------------------------------------===//
- /// DIEEntry - A pointer to another debug information entry. An instance of
- /// this class can also be used as a proxy for a debug information entry not
- /// yet defined (ie. types.)
- class DIEEntry : public DIEValue {
- DIE *const Entry;
- public:
- explicit DIEEntry(DIE *E) : DIEValue(isEntry), Entry(E) {
- assert(E && "Cannot construct a DIEEntry with a null DIE");
- }
+ /// EmitValue - Emit debug information entry offset.
+ ///
+ void EmitValue(AsmPrinter *AP, dwarf::Form Form) const override;
- DIE *getEntry() const { return Entry; }
+ /// SizeOf - Determine size of debug information entry in bytes.
+ ///
+ unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const override {
+ return Form == dwarf::DW_FORM_ref_addr ? getRefAddrSize(AP)
+ : sizeof(int32_t);
+ }
- /// EmitValue - Emit debug information entry offset.
- ///
- virtual void EmitValue(AsmPrinter *AP, dwarf::Form Form) const;
+ /// Returns size of a ref_addr entry.
+ static unsigned getRefAddrSize(AsmPrinter *AP);
- /// SizeOf - Determine size of debug information entry in bytes.
- ///
- virtual unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const {
- return Form == dwarf::DW_FORM_ref_addr ? getRefAddrSize(AP)
- : sizeof(int32_t);
- }
+ // Implement isa/cast/dyncast.
+ static bool classof(const DIEValue *E) { return E->getType() == isEntry; }
+
+#ifndef NDEBUG
+ void print(raw_ostream &O) const override;
+#endif
+};
+
+//===--------------------------------------------------------------------===//
+/// \brief A signature reference to a type unit.
+class DIETypeSignature : public DIEValue {
+ const DwarfTypeUnit &Unit;
+
+public:
+ explicit DIETypeSignature(const DwarfTypeUnit &Unit)
+ : DIEValue(isTypeSignature), Unit(Unit) {}
+
+ /// \brief Emit type unit signature.
+ void EmitValue(AsmPrinter *Asm, dwarf::Form Form) const override;
+
+ /// Returns size of a ref_sig8 entry.
+ unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const override {
+ assert(Form == dwarf::DW_FORM_ref_sig8);
+ return 8;
+ }
+
+ // \brief Implement isa/cast/dyncast.
+ static bool classof(const DIEValue *E) {
+ return E->getType() == isTypeSignature;
+ }
+#ifndef NDEBUG
+ void print(raw_ostream &O) const override;
+ void dump() const;
+#endif
+};
+
+//===--------------------------------------------------------------------===//
+/// DIELoc - Represents an expression location.
+//
+class DIELoc : public DIEValue, public DIE {
+ mutable unsigned Size; // Size in bytes excluding size header.
+public:
+ DIELoc() : DIEValue(isLoc), DIE(0), Size(0) {}
- /// Returns size of a ref_addr entry.
- static unsigned getRefAddrSize(AsmPrinter *AP);
+ /// ComputeSize - Calculate the size of the location expression.
+ ///
+ unsigned ComputeSize(AsmPrinter *AP) const;
- // Implement isa/cast/dyncast.
- static bool classof(const DIEValue *E) { return E->getType() == isEntry; }
+ /// BestForm - Choose the best form for data.
+ ///
+ dwarf::Form BestForm(unsigned DwarfVersion) const {
+ if (DwarfVersion > 3)
+ return dwarf::DW_FORM_exprloc;
+ // Pre-DWARF4 location expressions were blocks and not exprloc.
+ if ((unsigned char)Size == Size)
+ return dwarf::DW_FORM_block1;
+ if ((unsigned short)Size == Size)
+ return dwarf::DW_FORM_block2;
+ if ((unsigned int)Size == Size)
+ return dwarf::DW_FORM_block4;
+ return dwarf::DW_FORM_block;
+ }
+
+ /// EmitValue - Emit location data.
+ ///
+ void EmitValue(AsmPrinter *AP, dwarf::Form Form) const override;
+
+ /// SizeOf - Determine size of location data in bytes.
+ ///
+ unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const override;
+
+ // Implement isa/cast/dyncast.
+ static bool classof(const DIEValue *E) { return E->getType() == isLoc; }
#ifndef NDEBUG
- virtual void print(raw_ostream &O) const;
+ void print(raw_ostream &O) const override;
#endif
- };
+};
- //===--------------------------------------------------------------------===//
- /// DIEBlock - A block of values. Primarily used for location expressions.
- //
- class DIEBlock : public DIEValue, public DIE {
- unsigned Size; // Size in bytes excluding size header.
- public:
- DIEBlock() : DIEValue(isBlock), DIE(0), Size(0) {}
-
- /// ComputeSize - calculate the size of the block.
- ///
- unsigned ComputeSize(AsmPrinter *AP);
-
- /// BestForm - Choose the best form for data.
- ///
- dwarf::Form BestForm() const {
- if ((unsigned char)Size == Size) return dwarf::DW_FORM_block1;
- if ((unsigned short)Size == Size) return dwarf::DW_FORM_block2;
- if ((unsigned int)Size == Size) return dwarf::DW_FORM_block4;
- return dwarf::DW_FORM_block;
- }
+//===--------------------------------------------------------------------===//
+/// DIEBlock - Represents a block of values.
+//
+class DIEBlock : public DIEValue, public DIE {
+ mutable unsigned Size; // Size in bytes excluding size header.
+public:
+ DIEBlock() : DIEValue(isBlock), DIE(0), Size(0) {}
- /// EmitValue - Emit block data.
- ///
- virtual void EmitValue(AsmPrinter *AP, dwarf::Form Form) const;
+ /// ComputeSize - Calculate the size of the location expression.
+ ///
+ unsigned ComputeSize(AsmPrinter *AP) const;
- /// SizeOf - Determine size of block data in bytes.
- ///
- virtual unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const;
+ /// BestForm - Choose the best form for data.
+ ///
+ dwarf::Form BestForm() const {
+ if ((unsigned char)Size == Size)
+ return dwarf::DW_FORM_block1;
+ if ((unsigned short)Size == Size)
+ return dwarf::DW_FORM_block2;
+ if ((unsigned int)Size == Size)
+ return dwarf::DW_FORM_block4;
+ return dwarf::DW_FORM_block;
+ }
+
+ /// EmitValue - Emit location data.
+ ///
+ void EmitValue(AsmPrinter *AP, dwarf::Form Form) const override;
+
+ /// SizeOf - Determine size of location data in bytes.
+ ///
+ unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const override;
- // Implement isa/cast/dyncast.
- static bool classof(const DIEValue *E) { return E->getType() == isBlock; }
+ // Implement isa/cast/dyncast.
+ static bool classof(const DIEValue *E) { return E->getType() == isBlock; }
#ifndef NDEBUG
- virtual void print(raw_ostream &O) const;
+ void print(raw_ostream &O) const override;
#endif
- };
+};
+
+//===--------------------------------------------------------------------===//
+/// DIELocList - Represents a pointer to a location list in the debug_loc
+/// section.
+//
+class DIELocList : public DIEValue {
+ // Index into the .debug_loc vector.
+ size_t Index;
+
+public:
+ DIELocList(size_t I) : DIEValue(isLocList), Index(I) {}
+
+ /// getValue - Grab the current index out.
+ size_t getValue() const { return Index; }
+
+ /// EmitValue - Emit location data.
+ ///
+ void EmitValue(AsmPrinter *AP, dwarf::Form Form) const override;
+
+ /// SizeOf - Determine size of location data in bytes.
+ ///
+ unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const override;
+
+ // Implement isa/cast/dyncast.
+ static bool classof(const DIEValue *E) { return E->getType() == isLocList; }
+
+#ifndef NDEBUG
+ void print(raw_ostream &O) const override;
+#endif
+};
} // end llvm namespace
diff --git a/lib/CodeGen/AsmPrinter/DIEHash.cpp b/lib/CodeGen/AsmPrinter/DIEHash.cpp
index 95eca90ef0..74beec1c95 100644
--- a/lib/CodeGen/AsmPrinter/DIEHash.cpp
+++ b/lib/CodeGen/AsmPrinter/DIEHash.cpp
@@ -13,12 +13,13 @@
#define DEBUG_TYPE "dwarfdebug"
+#include "ByteStreamer.h"
#include "DIEHash.h"
-
#include "DIE.h"
-#include "DwarfCompileUnit.h"
+#include "DwarfDebug.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/Dwarf.h"
#include "llvm/Support/Endian.h"
@@ -75,7 +76,7 @@ void DIEHash::addSLEB128(int64_t Value) {
do {
uint8_t Byte = Value & 0x7f;
Value >>= 7;
- More = !((((Value == 0 ) && ((Byte & 0x40) == 0)) ||
+ More = !((((Value == 0) && ((Byte & 0x40) == 0)) ||
((Value == -1) && ((Byte & 0x40) != 0))));
if (More)
Byte |= 0x80; // Mark this byte to show that more bytes will follow.
@@ -92,10 +93,12 @@ void DIEHash::addParentContext(const DIE &Parent) {
// outermost such construct...
SmallVector<const DIE *, 1> Parents;
const DIE *Cur = &Parent;
- while (Cur->getTag() != dwarf::DW_TAG_compile_unit) {
+ while (Cur->getParent()) {
Parents.push_back(Cur);
Cur = Cur->getParent();
}
+ assert(Cur->getTag() == dwarf::DW_TAG_compile_unit ||
+ Cur->getTag() == dwarf::DW_TAG_type_unit);
// Reverse iterate over our list to go from the outermost construct to the
// innermost.
@@ -134,55 +137,55 @@ void DIEHash::collectAttributes(const DIE &Die, DIEAttrs &Attrs) {
<< dwarf::AttributeString(Abbrevs.getData()[i].getAttribute())
<< " added.\n");
switch (Abbrevs.getData()[i].getAttribute()) {
- COLLECT_ATTR(DW_AT_name);
- COLLECT_ATTR(DW_AT_accessibility);
- COLLECT_ATTR(DW_AT_address_class);
- COLLECT_ATTR(DW_AT_allocated);
- COLLECT_ATTR(DW_AT_artificial);
- COLLECT_ATTR(DW_AT_associated);
- COLLECT_ATTR(DW_AT_binary_scale);
- COLLECT_ATTR(DW_AT_bit_offset);
- COLLECT_ATTR(DW_AT_bit_size);
- COLLECT_ATTR(DW_AT_bit_stride);
- COLLECT_ATTR(DW_AT_byte_size);
- COLLECT_ATTR(DW_AT_byte_stride);
- COLLECT_ATTR(DW_AT_const_expr);
- COLLECT_ATTR(DW_AT_const_value);
- COLLECT_ATTR(DW_AT_containing_type);
- COLLECT_ATTR(DW_AT_count);
- COLLECT_ATTR(DW_AT_data_bit_offset);
- COLLECT_ATTR(DW_AT_data_location);
- COLLECT_ATTR(DW_AT_data_member_location);
- COLLECT_ATTR(DW_AT_decimal_scale);
- COLLECT_ATTR(DW_AT_decimal_sign);
- COLLECT_ATTR(DW_AT_default_value);
- COLLECT_ATTR(DW_AT_digit_count);
- COLLECT_ATTR(DW_AT_discr);
- COLLECT_ATTR(DW_AT_discr_list);
- COLLECT_ATTR(DW_AT_discr_value);
- COLLECT_ATTR(DW_AT_encoding);
- COLLECT_ATTR(DW_AT_enum_class);
- COLLECT_ATTR(DW_AT_endianity);
- COLLECT_ATTR(DW_AT_explicit);
- COLLECT_ATTR(DW_AT_is_optional);
- COLLECT_ATTR(DW_AT_location);
- COLLECT_ATTR(DW_AT_lower_bound);
- COLLECT_ATTR(DW_AT_mutable);
- COLLECT_ATTR(DW_AT_ordering);
- COLLECT_ATTR(DW_AT_picture_string);
- COLLECT_ATTR(DW_AT_prototyped);
- COLLECT_ATTR(DW_AT_small);
- COLLECT_ATTR(DW_AT_segment);
- COLLECT_ATTR(DW_AT_string_length);
- COLLECT_ATTR(DW_AT_threads_scaled);
- COLLECT_ATTR(DW_AT_upper_bound);
- COLLECT_ATTR(DW_AT_use_location);
- COLLECT_ATTR(DW_AT_use_UTF8);
- COLLECT_ATTR(DW_AT_variable_parameter);
- COLLECT_ATTR(DW_AT_virtuality);
- COLLECT_ATTR(DW_AT_visibility);
- COLLECT_ATTR(DW_AT_vtable_elem_location);
- COLLECT_ATTR(DW_AT_type);
+ COLLECT_ATTR(DW_AT_name);
+ COLLECT_ATTR(DW_AT_accessibility);
+ COLLECT_ATTR(DW_AT_address_class);
+ COLLECT_ATTR(DW_AT_allocated);
+ COLLECT_ATTR(DW_AT_artificial);
+ COLLECT_ATTR(DW_AT_associated);
+ COLLECT_ATTR(DW_AT_binary_scale);
+ COLLECT_ATTR(DW_AT_bit_offset);
+ COLLECT_ATTR(DW_AT_bit_size);
+ COLLECT_ATTR(DW_AT_bit_stride);
+ COLLECT_ATTR(DW_AT_byte_size);
+ COLLECT_ATTR(DW_AT_byte_stride);
+ COLLECT_ATTR(DW_AT_const_expr);
+ COLLECT_ATTR(DW_AT_const_value);
+ COLLECT_ATTR(DW_AT_containing_type);
+ COLLECT_ATTR(DW_AT_count);
+ COLLECT_ATTR(DW_AT_data_bit_offset);
+ COLLECT_ATTR(DW_AT_data_location);
+ COLLECT_ATTR(DW_AT_data_member_location);
+ COLLECT_ATTR(DW_AT_decimal_scale);
+ COLLECT_ATTR(DW_AT_decimal_sign);
+ COLLECT_ATTR(DW_AT_default_value);
+ COLLECT_ATTR(DW_AT_digit_count);
+ COLLECT_ATTR(DW_AT_discr);
+ COLLECT_ATTR(DW_AT_discr_list);
+ COLLECT_ATTR(DW_AT_discr_value);
+ COLLECT_ATTR(DW_AT_encoding);
+ COLLECT_ATTR(DW_AT_enum_class);
+ COLLECT_ATTR(DW_AT_endianity);
+ COLLECT_ATTR(DW_AT_explicit);
+ COLLECT_ATTR(DW_AT_is_optional);
+ COLLECT_ATTR(DW_AT_location);
+ COLLECT_ATTR(DW_AT_lower_bound);
+ COLLECT_ATTR(DW_AT_mutable);
+ COLLECT_ATTR(DW_AT_ordering);
+ COLLECT_ATTR(DW_AT_picture_string);
+ COLLECT_ATTR(DW_AT_prototyped);
+ COLLECT_ATTR(DW_AT_small);
+ COLLECT_ATTR(DW_AT_segment);
+ COLLECT_ATTR(DW_AT_string_length);
+ COLLECT_ATTR(DW_AT_threads_scaled);
+ COLLECT_ATTR(DW_AT_upper_bound);
+ COLLECT_ATTR(DW_AT_use_location);
+ COLLECT_ATTR(DW_AT_use_UTF8);
+ COLLECT_ATTR(DW_AT_variable_parameter);
+ COLLECT_ATTR(DW_AT_virtuality);
+ COLLECT_ATTR(DW_AT_visibility);
+ COLLECT_ATTR(DW_AT_vtable_elem_location);
+ COLLECT_ATTR(DW_AT_type);
default:
break;
}
@@ -269,6 +272,24 @@ void DIEHash::hashDIEEntry(dwarf::Attribute Attribute, dwarf::Tag Tag,
computeHash(Entry);
}
+// Hash all of the values in a block like set of values. This assumes that
+// all of the data is going to be added as integers.
+void DIEHash::hashBlockData(const SmallVectorImpl<DIEValue *> &Values) {
+ for (SmallVectorImpl<DIEValue *>::const_iterator I = Values.begin(),
+ E = Values.end();
+ I != E; ++I)
+ Hash.update((uint64_t)cast<DIEInteger>(*I)->getValue());
+}
+
+// Hash the contents of a loclistptr class.
+void DIEHash::hashLocList(const DIELocList &LocList) {
+ HashingByteStreamer Streamer(*this);
+ DwarfDebug &DD = *AP->getDwarfDebug();
+ for (const auto &Entry :
+ DD.getDebugLocEntries()[LocList.getValue()].List)
+ DD.emitDebugLocEntry(Streamer, Entry);
+}
+
// Hash an individual attribute \param Attr based on the type of attribute and
// the form.
void DIEHash::hashAttribute(AttrEntry Attr, dwarf::Tag Tag) {
@@ -276,43 +297,76 @@ void DIEHash::hashAttribute(AttrEntry Attr, dwarf::Tag Tag) {
const DIEAbbrevData *Desc = Attr.Desc;
dwarf::Attribute Attribute = Desc->getAttribute();
- // 7.27 Step 3
- // ... An attribute that refers to another type entry T is processed as
- // follows:
- if (const DIEEntry *EntryAttr = dyn_cast<DIEEntry>(Value)) {
- hashDIEEntry(Attribute, Tag, *EntryAttr->getEntry());
- return;
+ // Other attribute values use the letter 'A' as the marker, and the value
+ // consists of the form code (encoded as an unsigned LEB128 value) followed by
+ // the encoding of the value according to the form code. To ensure
+ // reproducibility of the signature, the set of forms used in the signature
+ // computation is limited to the following: DW_FORM_sdata, DW_FORM_flag,
+ // DW_FORM_string, and DW_FORM_block.
+
+ switch (Value->getType()) {
+ // 7.27 Step 3
+ // ... An attribute that refers to another type entry T is processed as
+ // follows:
+ case DIEValue::isEntry:
+ hashDIEEntry(Attribute, Tag, *cast<DIEEntry>(Value)->getEntry());
+ break;
+ case DIEValue::isInteger: {
+ addULEB128('A');
+ addULEB128(Attribute);
+ switch (Desc->getForm()) {
+ case dwarf::DW_FORM_data1:
+ case dwarf::DW_FORM_data2:
+ case dwarf::DW_FORM_data4:
+ case dwarf::DW_FORM_data8:
+ case dwarf::DW_FORM_udata:
+ case dwarf::DW_FORM_sdata:
+ addULEB128(dwarf::DW_FORM_sdata);
+ addSLEB128((int64_t)cast<DIEInteger>(Value)->getValue());
+ break;
+ // DW_FORM_flag_present is just flag with a value of one. We still give it a
+ // value so just use the value.
+ case dwarf::DW_FORM_flag_present:
+ case dwarf::DW_FORM_flag:
+ addULEB128(dwarf::DW_FORM_flag);
+ addULEB128((int64_t)cast<DIEInteger>(Value)->getValue());
+ break;
+ default:
+ llvm_unreachable("Unknown integer form!");
+ }
+ break;
}
-
- // Other attribute values use the letter 'A' as the marker, ...
- addULEB128('A');
-
- addULEB128(Attribute);
-
- // ... and the value consists of the form code (encoded as an unsigned LEB128
- // value) followed by the encoding of the value according to the form code. To
- // ensure reproducibility of the signature, the set of forms used in the
- // signature computation is limited to the following: DW_FORM_sdata,
- // DW_FORM_flag, DW_FORM_string, and DW_FORM_block.
- switch (Desc->getForm()) {
- case dwarf::DW_FORM_string:
- llvm_unreachable(
- "Add support for DW_FORM_string if we ever start emitting them again");
- case dwarf::DW_FORM_GNU_str_index:
- case dwarf::DW_FORM_strp:
+ case DIEValue::isString:
+ addULEB128('A');
+ addULEB128(Attribute);
addULEB128(dwarf::DW_FORM_string);
addString(cast<DIEString>(Value)->getString());
break;
- case dwarf::DW_FORM_data1:
- case dwarf::DW_FORM_data2:
- case dwarf::DW_FORM_data4:
- case dwarf::DW_FORM_data8:
- case dwarf::DW_FORM_udata:
- addULEB128(dwarf::DW_FORM_sdata);
- addSLEB128((int64_t)cast<DIEInteger>(Value)->getValue());
+ case DIEValue::isBlock:
+ case DIEValue::isLoc:
+ case DIEValue::isLocList:
+ addULEB128('A');
+ addULEB128(Attribute);
+ addULEB128(dwarf::DW_FORM_block);
+ if (isa<DIEBlock>(Value)) {
+ addULEB128(cast<DIEBlock>(Value)->ComputeSize(AP));
+ hashBlockData(cast<DIEBlock>(Value)->getValues());
+ } else if (isa<DIELoc>(Value)) {
+ addULEB128(cast<DIELoc>(Value)->ComputeSize(AP));
+ hashBlockData(cast<DIELoc>(Value)->getValues());
+ } else {
+ // We could add the block length, but that would take
+ // a bit of work and not add a lot of uniqueness
+ // to the hash in some way we could test.
+ hashLocList(*cast<DIELocList>(Value));
+ }
break;
- default:
- llvm_unreachable("Add support for additional forms");
+ // FIXME: It's uncertain whether or not we should handle this at the moment.
+ case DIEValue::isExpr:
+ case DIEValue::isLabel:
+ case DIEValue::isDelta:
+ case DIEValue::isTypeSignature:
+ llvm_unreachable("Add support for additional value types.");
}
}
diff --git a/lib/CodeGen/AsmPrinter/DIEHash.h b/lib/CodeGen/AsmPrinter/DIEHash.h
index f0c4ef98bb..48f16011e8 100644
--- a/lib/CodeGen/AsmPrinter/DIEHash.h
+++ b/lib/CodeGen/AsmPrinter/DIEHash.h
@@ -11,17 +11,22 @@
//
//===----------------------------------------------------------------------===//
+#ifndef CODEGEN_ASMPRINTER_DIEHASH_H__
+#define CODEGEN_ASMPRINTER_DIEHASH_H__
+
#include "DIE.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/Support/MD5.h"
namespace llvm {
+class AsmPrinter;
class CompileUnit;
/// \brief An object containing the capability of hashing and adding hash
/// attributes onto a DIE.
class DIEHash {
+
// The entry for a particular attribute.
struct AttrEntry {
const DIEValue *Val;
@@ -84,6 +89,8 @@ class DIEHash {
};
public:
+ DIEHash(AsmPrinter *A = NULL) : AP(A) {}
+
/// \brief Computes the ODR signature.
uint64_t computeDIEODRSignature(const DIE &Die);
@@ -105,13 +112,17 @@ private:
void computeHash(const DIE &Die);
// Routines that add DIEValues to the hash.
-private:
+public:
+ /// \brief Adds \param Value to the hash.
+ void update(uint8_t Value) { Hash.update(Value); }
+
/// \brief Encodes and adds \param Value to the hash as a ULEB128.
void addULEB128(uint64_t Value);
/// \brief Encodes and adds \param Value to the hash as a SLEB128.
void addSLEB128(int64_t Value);
+private:
/// \brief Adds \param Str to the hash and includes a NULL byte.
void addString(StringRef Str);
@@ -122,6 +133,13 @@ private:
/// \brief Hashes the attributes in \param Attrs in order.
void hashAttributes(const DIEAttrs &Attrs, dwarf::Tag Tag);
+ /// \brief Hashes the data in a block like DIEValue, e.g. DW_FORM_block or
+ /// DW_FORM_exprloc.
+ void hashBlockData(const SmallVectorImpl<DIEValue *> &Values);
+
+ /// \brief Hashes the contents pointed to in the .debug_loc section.
+ void hashLocList(const DIELocList &LocList);
+
/// \brief Hashes an individual attribute.
void hashAttribute(AttrEntry Attr, dwarf::Tag Tag);
@@ -136,12 +154,16 @@ private:
StringRef Name);
/// \brief Hashes a reference to a previously referenced type DIE.
- void hashRepeatedTypeReference(dwarf::Attribute Attribute, unsigned DieNumber);
+ void hashRepeatedTypeReference(dwarf::Attribute Attribute,
+ unsigned DieNumber);
void hashNestedType(const DIE &Die, StringRef Name);
private:
MD5 Hash;
+ AsmPrinter *AP;
DenseMap<const DIE *, unsigned> Numbering;
};
}
+
+#endif
diff --git a/lib/CodeGen/AsmPrinter/DebugLocEntry.h b/lib/CodeGen/AsmPrinter/DebugLocEntry.h
new file mode 100644
index 0000000000..470453fbe2
--- /dev/null
+++ b/lib/CodeGen/AsmPrinter/DebugLocEntry.h
@@ -0,0 +1,123 @@
+//===-- llvm/CodeGen/DebugLocEntry.h - Entry in debug_loc list -*- C++ -*--===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CODEGEN_ASMPRINTER_DEBUGLOCENTRY_H__
+#define CODEGEN_ASMPRINTER_DEBUGLOCENTRY_H__
+#include "llvm/IR/Constants.h"
+#include "llvm/MC/MachineLocation.h"
+#include "llvm/MC/MCSymbol.h"
+
+namespace llvm {
+class DwarfCompileUnit;
+class MDNode;
+/// \brief This struct describes location entries emitted in the .debug_loc
+/// section.
+class DebugLocEntry {
+ // Begin and end symbols for the address range that this location is valid.
+ const MCSymbol *Begin;
+ const MCSymbol *End;
+
+ // Type of entry that this represents.
+ enum EntryType { E_Location, E_Integer, E_ConstantFP, E_ConstantInt };
+ enum EntryType EntryKind;
+
+ union {
+ int64_t Int;
+ const ConstantFP *CFP;
+ const ConstantInt *CIP;
+ } Constants;
+
+ // The location in the machine frame.
+ MachineLocation Loc;
+
+ // The variable to which this location entry corresponds.
+ const MDNode *Variable;
+
+ // The compile unit to which this location entry is referenced by.
+ const DwarfCompileUnit *Unit;
+
+ bool hasSameValueOrLocation(const DebugLocEntry &Next) {
+ if (EntryKind != Next.EntryKind)
+ return false;
+
+ bool EqualValues;
+ switch (EntryKind) {
+ case E_Location:
+ EqualValues = Loc == Next.Loc;
+ break;
+ case E_Integer:
+ EqualValues = Constants.Int == Next.Constants.Int;
+ break;
+ case E_ConstantFP:
+ EqualValues = Constants.CFP == Next.Constants.CFP;
+ break;
+ case E_ConstantInt:
+ EqualValues = Constants.CIP == Next.Constants.CIP;
+ break;
+ }
+
+ return EqualValues;
+ }
+
+public:
+ DebugLocEntry() : Begin(0), End(0), Variable(0), Unit(0) {
+ Constants.Int = 0;
+ }
+ DebugLocEntry(const MCSymbol *B, const MCSymbol *E, MachineLocation &L,
+ const MDNode *V, const DwarfCompileUnit *U)
+ : Begin(B), End(E), Loc(L), Variable(V), Unit(U) {
+ Constants.Int = 0;
+ EntryKind = E_Location;
+ }
+ DebugLocEntry(const MCSymbol *B, const MCSymbol *E, int64_t i,
+ const DwarfCompileUnit *U)
+ : Begin(B), End(E), Variable(0), Unit(U) {
+ Constants.Int = i;
+ EntryKind = E_Integer;
+ }
+ DebugLocEntry(const MCSymbol *B, const MCSymbol *E, const ConstantFP *FPtr,
+ const DwarfCompileUnit *U)
+ : Begin(B), End(E), Variable(0), Unit(U) {
+ Constants.CFP = FPtr;
+ EntryKind = E_ConstantFP;
+ }
+ DebugLocEntry(const MCSymbol *B, const MCSymbol *E, const ConstantInt *IPtr,
+ const DwarfCompileUnit *U)
+ : Begin(B), End(E), Variable(0), Unit(U) {
+ Constants.CIP = IPtr;
+ EntryKind = E_ConstantInt;
+ }
+
+ /// \brief Attempt to merge this DebugLocEntry with Next and return
+ /// true if the merge was successful. Entries can be merged if they
+ /// share the same Loc/Constant and if Next immediately follows this
+ /// Entry.
+ bool Merge(const DebugLocEntry &Next) {
+ if (End == Next.Begin && hasSameValueOrLocation(Next)) {
+ End = Next.End;
+ return true;
+ }
+ return false;
+ }
+ bool isLocation() const { return EntryKind == E_Location; }
+ bool isInt() const { return EntryKind == E_Integer; }
+ bool isConstantFP() const { return EntryKind == E_ConstantFP; }
+ bool isConstantInt() const { return EntryKind == E_ConstantInt; }
+ int64_t getInt() const { return Constants.Int; }
+ const ConstantFP *getConstantFP() const { return Constants.CFP; }
+ const ConstantInt *getConstantInt() const { return Constants.CIP; }
+ const MDNode *getVariable() const { return Variable; }
+ const MCSymbol *getBeginSym() const { return Begin; }
+ const MCSymbol *getEndSym() const { return End; }
+ const DwarfCompileUnit *getCU() const { return Unit; }
+ MachineLocation getLoc() const { return Loc; }
+};
+
+}
+#endif
diff --git a/lib/CodeGen/AsmPrinter/DebugLocList.h b/lib/CodeGen/AsmPrinter/DebugLocList.h
new file mode 100644
index 0000000000..7a51c7bd5b
--- /dev/null
+++ b/lib/CodeGen/AsmPrinter/DebugLocList.h
@@ -0,0 +1,23 @@
+//===--- lib/CodeGen/DebugLocList.h - DWARF debug_loc list ------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CODEGEN_ASMPRINTER_DEBUGLOCLIST_H__
+#define CODEGEN_ASMPRINTER_DEBUGLOCLIST_H__
+
+#include "llvm/MC/MCSymbol.h"
+#include "llvm/ADT/SmallVector.h"
+#include "DebugLocEntry.h"
+
+namespace llvm {
+struct DebugLocList {
+ MCSymbol *Label;
+ SmallVector<DebugLocEntry, 4> List;
+};
+}
+#endif
diff --git a/lib/CodeGen/AsmPrinter/DwarfAccelTable.cpp b/lib/CodeGen/AsmPrinter/DwarfAccelTable.cpp
index 689aeda86a..bcbb6c8455 100644
--- a/lib/CodeGen/AsmPrinter/DwarfAccelTable.cpp
+++ b/lib/CodeGen/AsmPrinter/DwarfAccelTable.cpp
@@ -31,7 +31,7 @@ DwarfAccelTable::DwarfAccelTable(ArrayRef<DwarfAccelTable::Atom> atomList)
DwarfAccelTable::~DwarfAccelTable() {}
-void DwarfAccelTable::AddName(StringRef Name, DIE *die, char Flags) {
+void DwarfAccelTable::AddName(StringRef Name, const DIE *die, char Flags) {
assert(Data.empty() && "Already finalized!");
// If the string is in the list already then add this die to the list
// otherwise add a new one.
@@ -172,7 +172,7 @@ void DwarfAccelTable::EmitOffsets(AsmPrinter *Asm, MCSymbol *SecBegin) {
// Walk through the buckets and emit the full data for each element in
// the bucket. For the string case emit the dies and the various offsets.
// Terminate each HashData bucket with 0.
-void DwarfAccelTable::EmitData(AsmPrinter *Asm, DwarfUnits *D) {
+void DwarfAccelTable::EmitData(AsmPrinter *Asm, DwarfFile *D) {
uint64_t PrevHash = UINT64_MAX;
for (size_t i = 0, e = Buckets.size(); i < e; ++i) {
for (HashList::const_iterator HI = Buckets[i].begin(),
@@ -207,7 +207,7 @@ void DwarfAccelTable::EmitData(AsmPrinter *Asm, DwarfUnits *D) {
}
// Emit the entire data structure to the output file.
-void DwarfAccelTable::Emit(AsmPrinter *Asm, MCSymbol *SecBegin, DwarfUnits *D) {
+void DwarfAccelTable::Emit(AsmPrinter *Asm, MCSymbol *SecBegin, DwarfFile *D) {
// Emit the header.
EmitHeader(Asm);
diff --git a/lib/CodeGen/AsmPrinter/DwarfAccelTable.h b/lib/CodeGen/AsmPrinter/DwarfAccelTable.h
index 7627313d28..4a144978b0 100644
--- a/lib/CodeGen/AsmPrinter/DwarfAccelTable.h
+++ b/lib/CodeGen/AsmPrinter/DwarfAccelTable.h
@@ -24,7 +24,6 @@
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/FormattedStream.h"
-#include <map>
#include <vector>
// The dwarf accelerator tables are an indirect hash table optimized
@@ -62,8 +61,7 @@
namespace llvm {
class AsmPrinter;
-class DIE;
-class DwarfUnits;
+class DwarfFile;
class DwarfAccelTable {
@@ -165,10 +163,10 @@ private:
// HashData[hash_data_count]
public:
struct HashDataContents {
- DIE *Die; // Offsets
+ const DIE *Die; // Offsets
char Flags; // Specific flags to output
- HashDataContents(DIE *D, char Flags) : Die(D), Flags(Flags) {}
+ HashDataContents(const DIE *D, char Flags) : Die(D), Flags(Flags) {}
#ifndef NDEBUG
void print(raw_ostream &O) const {
O << " Offset: " << Die->getOffset() << "\n";
@@ -216,7 +214,7 @@ private:
void EmitBuckets(AsmPrinter *);
void EmitHashes(AsmPrinter *);
void EmitOffsets(AsmPrinter *, MCSymbol *);
- void EmitData(AsmPrinter *, DwarfUnits *D);
+ void EmitData(AsmPrinter *, DwarfFile *D);
// Allocator for HashData and HashDataContents.
BumpPtrAllocator Allocator;
@@ -241,9 +239,9 @@ private:
public:
DwarfAccelTable(ArrayRef<DwarfAccelTable::Atom>);
~DwarfAccelTable();
- void AddName(StringRef, DIE *, char = 0);
+ void AddName(StringRef, const DIE *, char = 0);
void FinalizeTable(AsmPrinter *, StringRef);
- void Emit(AsmPrinter *, MCSymbol *, DwarfUnits *);
+ void Emit(AsmPrinter *, MCSymbol *, DwarfFile *);
#ifndef NDEBUG
void print(raw_ostream &O);
void dump() { print(dbgs()); }
diff --git a/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp b/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp
index 8918f3de0a..30312ac2e2 100644
--- a/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp
+++ b/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp
@@ -20,6 +20,7 @@
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/IR/DataLayout.h"
+#include "llvm/IR/Mangler.h"
#include "llvm/IR/Module.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCContext.h"
@@ -31,7 +32,6 @@
#include "llvm/Support/Dwarf.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FormattedStream.h"
-#include "llvm/Target/Mangler.h"
#include "llvm/Target/TargetFrameLowering.h"
#include "llvm/Target/TargetLoweringObjectFile.h"
#include "llvm/Target/TargetMachine.h"
@@ -46,9 +46,9 @@ DwarfCFIException::DwarfCFIException(AsmPrinter *A)
DwarfCFIException::~DwarfCFIException() {}
-/// EndModule - Emit all exception information that should come after the
+/// endModule - Emit all exception information that should come after the
/// content.
-void DwarfCFIException::EndModule() {
+void DwarfCFIException::endModule() {
if (moveTypeModule == AsmPrinter::CFI_M_Debug)
Asm->OutStreamer.EmitCFISections(false, true);
@@ -82,9 +82,9 @@ void DwarfCFIException::EndModule() {
}
}
-/// BeginFunction - Gather pre-function exception information. Assumes it's
+/// beginFunction - Gather pre-function exception information. Assumes it's
/// being emitted immediately after the function entry point.
-void DwarfCFIException::BeginFunction(const MachineFunction *MF) {
+void DwarfCFIException::beginFunction(const MachineFunction *MF) {
shouldEmitMoves = shouldEmitPersonality = shouldEmitLSDA = false;
// If any landing pads survive, we need an EH table.
@@ -113,13 +113,14 @@ void DwarfCFIException::BeginFunction(const MachineFunction *MF) {
if (!shouldEmitPersonality && !shouldEmitMoves)
return;
- Asm->OutStreamer.EmitCFIStartProc();
+ Asm->OutStreamer.EmitCFIStartProc(/*IsSimple=*/false);
// Indicate personality routine, if any.
if (!shouldEmitPersonality)
return;
- const MCSymbol *Sym = TLOF.getCFIPersonalitySymbol(Per, Asm->Mang, MMI);
+ const MCSymbol *Sym =
+ TLOF.getCFIPersonalitySymbol(Per, *Asm->Mang, Asm->TM, MMI);
Asm->OutStreamer.EmitCFIPersonality(Sym, PerEncoding);
Asm->OutStreamer.EmitDebugLabel
@@ -135,9 +136,9 @@ void DwarfCFIException::BeginFunction(const MachineFunction *MF) {
LSDAEncoding);
}
-/// EndFunction - Gather and emit post-function exception information.
+/// endFunction - Gather and emit post-function exception information.
///
-void DwarfCFIException::EndFunction() {
+void DwarfCFIException::endFunction(const MachineFunction *) {
if (!shouldEmitPersonality && !shouldEmitMoves)
return;
diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
index 24e2c05398..11345eb288 100644
--- a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
+++ b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
@@ -12,23 +12,25 @@
//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "dwarfdebug"
+#include "ByteStreamer.h"
#include "DwarfDebug.h"
#include "DIE.h"
#include "DIEHash.h"
#include "DwarfAccelTable.h"
-#include "DwarfCompileUnit.h"
+#include "DwarfUnit.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/Triple.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
-#include "llvm/DIBuilder.h"
-#include "llvm/DebugInfo.h"
#include "llvm/IR/Constants.h"
+#include "llvm/IR/DIBuilder.h"
#include "llvm/IR/DataLayout.h"
+#include "llvm/IR/DebugInfo.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Module.h"
+#include "llvm/IR/ValueHandle.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCSection.h"
#include "llvm/MC/MCStreamer.h"
@@ -38,10 +40,10 @@
#include "llvm/Support/Dwarf.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FormattedStream.h"
+#include "llvm/Support/LEB128.h"
#include "llvm/Support/MD5.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/Timer.h"
-#include "llvm/Support/ValueHandle.h"
#include "llvm/Target/TargetFrameLowering.h"
#include "llvm/Target/TargetLoweringObjectFile.h"
#include "llvm/Target/TargetMachine.h"
@@ -59,26 +61,17 @@ static cl::opt<bool> UnknownLocations(
cl::init(false));
static cl::opt<bool>
-GenerateODRHash("generate-odr-hash", cl::Hidden,
- cl::desc("Add an ODR hash to external type DIEs."),
- cl::init(false));
-
-static cl::opt<bool>
-GenerateCUHash("generate-cu-hash", cl::Hidden,
- cl::desc("Add the CU hash as the dwo_id."),
- cl::init(false));
-
-static cl::opt<bool>
GenerateGnuPubSections("generate-gnu-dwarf-pub-sections", cl::Hidden,
cl::desc("Generate GNU-style pubnames and pubtypes"),
cl::init(false));
+static cl::opt<bool> GenerateARangeSection("generate-arange-section",
+ cl::Hidden,
+ cl::desc("Generate dwarf aranges"),
+ cl::init(false));
+
namespace {
-enum DefaultOnOff {
- Default,
- Enable,
- Disable
-};
+enum DefaultOnOff { Default, Enable, Disable };
}
static cl::opt<DefaultOnOff>
@@ -91,7 +84,7 @@ DwarfAccelTables("dwarf-accel-tables", cl::Hidden,
static cl::opt<DefaultOnOff>
SplitDwarf("split-dwarf", cl::Hidden,
- cl::desc("Output prototype dwarf split debug info."),
+ cl::desc("Output DWARF5 split debug info."),
cl::values(clEnumVal(Default, "Default for platform"),
clEnumVal(Enable, "Enabled"),
clEnumVal(Disable, "Disabled"), clEnumValEnd),
@@ -105,29 +98,34 @@ DwarfPubSections("generate-dwarf-pub-sections", cl::Hidden,
clEnumVal(Disable, "Disabled"), clEnumValEnd),
cl::init(Default));
+static cl::opt<unsigned>
+DwarfVersionNumber("dwarf-version", cl::Hidden,
+ cl::desc("Generate DWARF for dwarf version."), cl::init(0));
+
static const char *const DWARFGroupName = "DWARF Emission";
static const char *const DbgTimerName = "DWARF Debug Writer";
//===----------------------------------------------------------------------===//
-// Configuration values for initial hash set sizes (log2).
-//
-static const unsigned InitAbbreviationsSetSize = 9; // log2(512)
-
namespace llvm {
/// resolve - Look in the DwarfDebug map for the MDNode that
/// corresponds to the reference.
-template <typename T>
-T DbgVariable::resolve(DIRef<T> Ref) const {
+template <typename T> T DbgVariable::resolve(DIRef<T> Ref) const {
return DD->resolve(Ref);
}
+bool DbgVariable::isBlockByrefVariable() const {
+ assert(Var.isVariable() && "Invalid complex DbgVariable!");
+ return Var.isBlockByrefVariable(DD->getTypeIdentifierMap());
+}
+
+
DIType DbgVariable::getType() const {
- DIType Ty = Var.getType();
+ DIType Ty = Var.getType().resolve(DD->getTypeIdentifierMap());
// FIXME: isBlockByrefVariable should be reformulated in terms of complex
// addresses instead.
- if (Var.isBlockByrefVariable()) {
+ if (Var.isBlockByrefVariable(DD->getTypeIdentifierMap())) {
/* 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
@@ -179,22 +177,18 @@ static unsigned getDwarfVersionFromModule(const Module *M) {
}
DwarfDebug::DwarfDebug(AsmPrinter *A, Module *M)
- : Asm(A), MMI(Asm->MMI), FirstCU(0),
- AbbreviationsSet(InitAbbreviationsSetSize),
- SourceIdMap(DIEValueAllocator),
- PrevLabel(NULL), GlobalCUIndexCount(0),
- InfoHolder(A, &AbbreviationsSet, Abbreviations, "info_string",
- DIEValueAllocator),
- SkeletonAbbrevSet(InitAbbreviationsSetSize),
- SkeletonHolder(A, &SkeletonAbbrevSet, SkeletonAbbrevs, "skel_string",
- DIEValueAllocator) {
-
- DwarfInfoSectionSym = DwarfAbbrevSectionSym = 0;
- DwarfStrSectionSym = TextSectionSym = 0;
+ : Asm(A), MMI(Asm->MMI), FirstCU(0), PrevLabel(NULL), GlobalRangeCount(0),
+ InfoHolder(A, "info_string", DIEValueAllocator),
+ UsedNonDefaultText(false),
+ SkeletonHolder(A, "skel_string", DIEValueAllocator) {
+
+ DwarfInfoSectionSym = DwarfAbbrevSectionSym = DwarfStrSectionSym = 0;
DwarfDebugRangeSectionSym = DwarfDebugLocSectionSym = DwarfLineSectionSym = 0;
DwarfAddrSectionSym = 0;
DwarfAbbrevDWOSectionSym = DwarfStrDWOSectionSym = 0;
FunctionBeginSym = FunctionEndSym = 0;
+ CurFn = 0;
+ CurMI = 0;
// Turn on accelerator tables for Darwin by default, pubnames by
// default for non-Darwin, and handle split dwarf.
@@ -215,7 +209,9 @@ DwarfDebug::DwarfDebug(AsmPrinter *A, Module *M)
else
HasDwarfPubSections = DwarfPubSections == Enable;
- DwarfVersion = getDwarfVersionFromModule(MMI->getModule());
+ DwarfVersion = DwarfVersionNumber
+ ? DwarfVersionNumber
+ : getDwarfVersionFromModule(MMI->getModule());
{
NamedRegionTimer T(DbgTimerName, DWARFGroupName, TimePassesIsEnabled);
@@ -228,53 +224,57 @@ DwarfDebug::DwarfDebug(AsmPrinter *A, Module *M)
static MCSymbol *emitSectionSym(AsmPrinter *Asm, const MCSection *Section,
const char *SymbolStem = 0) {
Asm->OutStreamer.SwitchSection(Section);
- if (!SymbolStem) return 0;
+ if (!SymbolStem)
+ return 0;
MCSymbol *TmpSym = Asm->GetTempSymbol(SymbolStem);
Asm->OutStreamer.EmitLabel(TmpSym);
return TmpSym;
}
-MCSymbol *DwarfUnits::getStringPoolSym() {
+DwarfFile::~DwarfFile() {
+ for (DwarfUnit *DU : CUs)
+ delete DU;
+}
+
+MCSymbol *DwarfFile::getStringPoolSym() {
return Asm->GetTempSymbol(StringPref);
}
-MCSymbol *DwarfUnits::getStringPoolEntry(StringRef Str) {
- std::pair<MCSymbol*, unsigned> &Entry =
- StringPool.GetOrCreateValue(Str).getValue();
- if (Entry.first) return Entry.first;
+MCSymbol *DwarfFile::getStringPoolEntry(StringRef Str) {
+ std::pair<MCSymbol *, unsigned> &Entry =
+ StringPool.GetOrCreateValue(Str).getValue();
+ if (Entry.first)
+ return Entry.first;
Entry.second = NextStringPoolNumber++;
return Entry.first = Asm->GetTempSymbol(StringPref, Entry.second);
}
-unsigned DwarfUnits::getStringPoolIndex(StringRef Str) {
- std::pair<MCSymbol*, unsigned> &Entry =
- StringPool.GetOrCreateValue(Str).getValue();
- if (Entry.first) return Entry.second;
+unsigned DwarfFile::getStringPoolIndex(StringRef Str) {
+ std::pair<MCSymbol *, unsigned> &Entry =
+ StringPool.GetOrCreateValue(Str).getValue();
+ if (Entry.first)
+ return Entry.second;
Entry.second = NextStringPoolNumber++;
Entry.first = Asm->GetTempSymbol(StringPref, Entry.second);
return Entry.second;
}
-unsigned DwarfUnits::getAddrPoolIndex(const MCSymbol *Sym) {
- return getAddrPoolIndex(MCSymbolRefExpr::Create(Sym, Asm->OutContext));
-}
-
-unsigned DwarfUnits::getAddrPoolIndex(const MCExpr *Sym) {
- std::pair<DenseMap<const MCExpr *, unsigned>::iterator, bool> P =
- AddressPool.insert(std::make_pair(Sym, NextAddrPoolNumber));
+unsigned DwarfFile::getAddrPoolIndex(const MCSymbol *Sym, bool TLS) {
+ std::pair<AddrPool::iterator, bool> P = AddressPool.insert(
+ std::make_pair(Sym, AddressPoolEntry(NextAddrPoolNumber, TLS)));
if (P.second)
++NextAddrPoolNumber;
- return P.first->second;
+ return P.first->second.Number;
}
// Define a unique number for the abbreviation.
//
-void DwarfUnits::assignAbbrevNumber(DIEAbbrev &Abbrev) {
+void DwarfFile::assignAbbrevNumber(DIEAbbrev &Abbrev) {
// Check the set for priors.
- DIEAbbrev *InSet = AbbreviationsSet->GetOrInsertNode(&Abbrev);
+ DIEAbbrev *InSet = AbbreviationsSet.GetOrInsertNode(&Abbrev);
// If it's newly added.
if (InSet == &Abbrev) {
@@ -294,7 +294,8 @@ static bool isObjCClass(StringRef Name) {
}
static bool hasObjCCategory(StringRef Name) {
- if (!isObjCClass(Name)) return false;
+ if (!isObjCClass(Name))
+ return false;
return Name.find(") ") != StringRef::npos;
}
@@ -318,35 +319,35 @@ static StringRef getObjCMethodName(StringRef In) {
// Helper for sorting sections into a stable output order.
static bool SectionSort(const MCSection *A, const MCSection *B) {
- std::string LA = (A ? A->getLabelBeginName() : "");
- std::string LB = (B ? B->getLabelBeginName() : "");
- return LA < LB;
+ std::string LA = (A ? A->getLabelBeginName() : "");
+ std::string LB = (B ? B->getLabelBeginName() : "");
+ return LA < LB;
}
// Add the various names to the Dwarf accelerator table names.
// TODO: Determine whether or not we should add names for programs
// that do not have a DW_AT_name or DW_AT_linkage_name field - this
// is only slightly different than the lookup of non-standard ObjC names.
-static void addSubprogramNames(CompileUnit *TheCU, DISubprogram SP,
- DIE* Die) {
- if (!SP.isDefinition()) return;
- TheCU->addAccelName(SP.getName(), Die);
+static void addSubprogramNames(DwarfUnit *TheU, DISubprogram SP, DIE *Die) {
+ if (!SP.isDefinition())
+ return;
+ TheU->addAccelName(SP.getName(), Die);
// If the linkage name is different than the name, go ahead and output
// that as well into the name table.
if (SP.getLinkageName() != "" && SP.getName() != SP.getLinkageName())
- TheCU->addAccelName(SP.getLinkageName(), Die);
+ TheU->addAccelName(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);
- TheCU->addAccelObjC(Class, Die);
+ TheU->addAccelObjC(Class, Die);
if (Category != "")
- TheCU->addAccelObjC(Category, Die);
+ TheU->addAccelObjC(Category, Die);
// Also add the base method name to the name table.
- TheCU->addAccelName(getObjCMethodName(SP.getName()), Die);
+ TheU->addAccelName(getObjCMethodName(SP.getName()), Die);
}
}
@@ -366,7 +367,8 @@ bool DwarfDebug::isSubprogramContext(const MDNode *Context) {
// Find DIE for the given subprogram and attach appropriate DW_AT_low_pc
// and DW_AT_high_pc attributes. If there are global variables in this
// scope then create and insert DIEs for these variables.
-DIE *DwarfDebug::updateSubprogramScopeDIE(CompileUnit *SPCU, DISubprogram SP) {
+DIE *DwarfDebug::updateSubprogramScopeDIE(DwarfCompileUnit *SPCU,
+ DISubprogram SP) {
DIE *SPDie = SPCU->getDIE(SP);
assert(SPDie && "Unable to find subprogram DIE!");
@@ -376,7 +378,8 @@ DIE *DwarfDebug::updateSubprogramScopeDIE(CompileUnit *SPCU, DISubprogram SP) {
// concrete DIE twice.
if (DIE *AbsSPDIE = AbstractSPDies.lookup(SP)) {
// Pick up abstract subprogram DIE.
- SPDie = SPCU->createAndAddDIE(dwarf::DW_TAG_subprogram, *SPCU->getCUDie());
+ SPDie =
+ SPCU->createAndAddDIE(dwarf::DW_TAG_subprogram, *SPCU->getUnitDie());
SPCU->addDIEEntry(SPDie, dwarf::DW_AT_abstract_origin, AbsSPDIE);
} else {
DISubprogram SPDecl = SP.getFunctionDeclaration();
@@ -388,8 +391,7 @@ DIE *DwarfDebug::updateSubprogramScopeDIE(CompileUnit *SPCU, DISubprogram SP) {
// specification DIE for a function defined inside a function.
DIScope SPContext = resolve(SP.getContext());
if (SP.isDefinition() && !SPContext.isCompileUnit() &&
- !SPContext.isFile() &&
- !isSubprogramContext(SPContext)) {
+ !SPContext.isFile() && !isSubprogramContext(SPContext)) {
SPCU->addFlag(SPDie, dwarf::DW_AT_declaration);
// Add arguments.
@@ -397,30 +399,17 @@ DIE *DwarfDebug::updateSubprogramScopeDIE(CompileUnit *SPCU, DISubprogram SP) {
DIArray Args = SPTy.getTypeArray();
uint16_t SPTag = SPTy.getTag();
if (SPTag == dwarf::DW_TAG_subroutine_type)
- for (unsigned i = 1, N = Args.getNumElements(); i < N; ++i) {
- DIE *Arg =
- SPCU->createAndAddDIE(dwarf::DW_TAG_formal_parameter, *SPDie);
- DIType ATy(Args.getElement(i));
- SPCU->addType(Arg, ATy);
- if (ATy.isArtificial())
- SPCU->addFlag(Arg, dwarf::DW_AT_artificial);
- if (ATy.isObjectPointer())
- SPCU->addDIEEntry(SPDie, dwarf::DW_AT_object_pointer, Arg);
- }
+ SPCU->constructSubprogramArguments(*SPDie, Args);
DIE *SPDeclDie = SPDie;
- SPDie =
- SPCU->createAndAddDIE(dwarf::DW_TAG_subprogram, *SPCU->getCUDie());
+ SPDie = SPCU->createAndAddDIE(dwarf::DW_TAG_subprogram,
+ *SPCU->getUnitDie());
SPCU->addDIEEntry(SPDie, dwarf::DW_AT_specification, SPDeclDie);
}
}
}
- SPCU->addLabelAddress(SPDie, dwarf::DW_AT_low_pc,
- Asm->GetTempSymbol("func_begin",
- Asm->getFunctionNumber()));
- SPCU->addLabelAddress(SPDie, dwarf::DW_AT_high_pc,
- Asm->GetTempSymbol("func_end",
- Asm->getFunctionNumber()));
+ attachLowHighPC(SPCU, SPDie, FunctionBeginSym, FunctionEndSym);
+
const TargetRegisterInfo *RI = Asm->TM.getRegisterInfo();
MachineLocation Location(RI->getFrameRegister(*Asm->MF));
SPCU->addAddress(SPDie, dwarf::DW_AT_frame_base, Location);
@@ -453,9 +442,43 @@ bool DwarfDebug::isLexicalScopeDIENull(LexicalScope *Scope) {
return !End;
}
+static void addSectionLabel(AsmPrinter *Asm, DwarfUnit *U, DIE *D,
+ dwarf::Attribute A, const MCSymbol *L,
+ const MCSymbol *Sec) {
+ if (Asm->MAI->doesDwarfUseRelocationsAcrossSections())
+ U->addSectionLabel(D, A, L);
+ else
+ U->addSectionDelta(D, A, L, Sec);
+}
+
+void DwarfDebug::addScopeRangeList(DwarfCompileUnit *TheCU, DIE *ScopeDIE,
+ const SmallVectorImpl<InsnRange> &Range) {
+ // Emit offset in .debug_range as a relocatable label. emitDIE will handle
+ // emitting it appropriately.
+ MCSymbol *RangeSym = Asm->GetTempSymbol("debug_ranges", GlobalRangeCount++);
+
+ // Under fission, ranges are specified by constant offsets relative to the
+ // CU's DW_AT_GNU_ranges_base.
+ if (useSplitDwarf())
+ TheCU->addSectionDelta(ScopeDIE, dwarf::DW_AT_ranges, RangeSym,
+ DwarfDebugRangeSectionSym);
+ else
+ addSectionLabel(Asm, TheCU, ScopeDIE, dwarf::DW_AT_ranges, RangeSym,
+ DwarfDebugRangeSectionSym);
+
+ RangeSpanList List(RangeSym);
+ for (const InsnRange &R : Range) {
+ RangeSpan Span(getLabelBeforeInsn(R.first), getLabelAfterInsn(R.second));
+ List.addRange(std::move(Span));
+ }
+
+ // Add the range list to the set of ranges to be emitted.
+ TheCU->addRangeList(std::move(List));
+}
+
// Construct new DW_TAG_lexical_block for this scope and attach
// DW_AT_low_pc/DW_AT_high_pc labels.
-DIE *DwarfDebug::constructLexicalScopeDIE(CompileUnit *TheCU,
+DIE *DwarfDebug::constructLexicalScopeDIE(DwarfCompileUnit *TheCU,
LexicalScope *Scope) {
if (isLexicalScopeDIENull(Scope))
return 0;
@@ -464,29 +487,16 @@ DIE *DwarfDebug::constructLexicalScopeDIE(CompileUnit *TheCU,
if (Scope->isAbstractScope())
return ScopeDIE;
- const SmallVectorImpl<InsnRange> &Ranges = Scope->getRanges();
- // If we have multiple ranges, emit them into the range section.
- if (Ranges.size() > 1) {
- // .debug_range section has not been laid out yet. Emit offset in
- // .debug_range as a uint, size 4, for now. emitDIE will handle
- // DW_AT_ranges appropriately.
- TheCU->addUInt(ScopeDIE, dwarf::DW_AT_ranges, dwarf::DW_FORM_data4,
- DebugRangeSymbols.size()
- * Asm->getDataLayout().getPointerSize());
- for (SmallVectorImpl<InsnRange>::const_iterator RI = Ranges.begin(),
- RE = Ranges.end(); RI != RE; ++RI) {
- DebugRangeSymbols.push_back(getLabelBeforeInsn(RI->first));
- DebugRangeSymbols.push_back(getLabelAfterInsn(RI->second));
- }
+ const SmallVectorImpl<InsnRange> &ScopeRanges = Scope->getRanges();
- // Terminate the range list.
- DebugRangeSymbols.push_back(NULL);
- DebugRangeSymbols.push_back(NULL);
+ // If we have multiple ranges, emit them into the range section.
+ if (ScopeRanges.size() > 1) {
+ addScopeRangeList(TheCU, ScopeDIE, ScopeRanges);
return ScopeDIE;
}
// Construct the address range for this DIE.
- SmallVectorImpl<InsnRange>::const_iterator RI = Ranges.begin();
+ SmallVectorImpl<InsnRange>::const_iterator RI = ScopeRanges.begin();
MCSymbol *Start = getLabelBeforeInsn(RI->first);
MCSymbol *End = getLabelAfterInsn(RI->second);
assert(End && "End label should not be null!");
@@ -494,18 +504,17 @@ DIE *DwarfDebug::constructLexicalScopeDIE(CompileUnit *TheCU,
assert(Start->isDefined() && "Invalid starting label for an inlined scope!");
assert(End->isDefined() && "Invalid end label for an inlined scope!");
- TheCU->addLabelAddress(ScopeDIE, dwarf::DW_AT_low_pc, Start);
- TheCU->addLabelAddress(ScopeDIE, dwarf::DW_AT_high_pc, End);
+ attachLowHighPC(TheCU, ScopeDIE, Start, End);
return ScopeDIE;
}
// This scope represents inlined body of a function. Construct DIE to
// represent this concrete inlined copy of the function.
-DIE *DwarfDebug::constructInlinedScopeDIE(CompileUnit *TheCU,
+DIE *DwarfDebug::constructInlinedScopeDIE(DwarfCompileUnit *TheCU,
LexicalScope *Scope) {
- const SmallVectorImpl<InsnRange> &Ranges = Scope->getRanges();
- assert(Ranges.empty() == false &&
+ const SmallVectorImpl<InsnRange> &ScopeRanges = Scope->getRanges();
+ assert(!ScopeRanges.empty() &&
"LexicalScope does not have instruction markers!");
if (!Scope->getScopeNode())
@@ -521,22 +530,11 @@ DIE *DwarfDebug::constructInlinedScopeDIE(CompileUnit *TheCU,
DIE *ScopeDIE = new DIE(dwarf::DW_TAG_inlined_subroutine);
TheCU->addDIEEntry(ScopeDIE, dwarf::DW_AT_abstract_origin, OriginDIE);
- if (Ranges.size() > 1) {
- // .debug_range section has not been laid out yet. Emit offset in
- // .debug_range as a uint, size 4, for now. emitDIE will handle
- // DW_AT_ranges appropriately.
- TheCU->addUInt(ScopeDIE, dwarf::DW_AT_ranges, dwarf::DW_FORM_data4,
- DebugRangeSymbols.size()
- * Asm->getDataLayout().getPointerSize());
- for (SmallVectorImpl<InsnRange>::const_iterator RI = Ranges.begin(),
- RE = Ranges.end(); RI != RE; ++RI) {
- DebugRangeSymbols.push_back(getLabelBeforeInsn(RI->first));
- DebugRangeSymbols.push_back(getLabelAfterInsn(RI->second));
- }
- DebugRangeSymbols.push_back(NULL);
- DebugRangeSymbols.push_back(NULL);
- } else {
- SmallVectorImpl<InsnRange>::const_iterator RI = Ranges.begin();
+ // If we have multiple ranges, emit them into the range section.
+ if (ScopeRanges.size() > 1)
+ addScopeRangeList(TheCU, ScopeDIE, ScopeRanges);
+ else {
+ SmallVectorImpl<InsnRange>::const_iterator RI = ScopeRanges.begin();
MCSymbol *StartLabel = getLabelBeforeInsn(RI->first);
MCSymbol *EndLabel = getLabelAfterInsn(RI->second);
@@ -547,17 +545,16 @@ DIE *DwarfDebug::constructInlinedScopeDIE(CompileUnit *TheCU,
"Invalid starting label for an inlined scope!");
assert(EndLabel->isDefined() && "Invalid end label for an inlined scope!");
- TheCU->addLabelAddress(ScopeDIE, dwarf::DW_AT_low_pc, StartLabel);
- TheCU->addLabelAddress(ScopeDIE, dwarf::DW_AT_high_pc, EndLabel);
+ attachLowHighPC(TheCU, ScopeDIE, StartLabel, EndLabel);
}
InlinedSubprogramDIEs.insert(OriginDIE);
// Add the call site information to the DIE.
DILocation DL(Scope->getInlinedAt());
- TheCU->addUInt(ScopeDIE, dwarf::DW_AT_call_file, None,
- getOrCreateSourceID(DL.getFilename(), DL.getDirectory(),
- TheCU->getUniqueID()));
+ TheCU->addUInt(
+ ScopeDIE, dwarf::DW_AT_call_file, None,
+ TheCU->getOrCreateSourceID(DL.getFilename(), DL.getDirectory()));
TheCU->addUInt(ScopeDIE, dwarf::DW_AT_call_line, None, DL.getLineNumber());
// Add name to the name table, we do this here because we're guaranteed
@@ -567,37 +564,49 @@ DIE *DwarfDebug::constructInlinedScopeDIE(CompileUnit *TheCU,
return ScopeDIE;
}
-DIE *DwarfDebug::createScopeChildrenDIE(CompileUnit *TheCU, LexicalScope *Scope,
- SmallVectorImpl<DIE*> &Children) {
- DIE *ObjectPointer = NULL;
+DIE *DwarfDebug::createScopeChildrenDIE(DwarfCompileUnit *TheCU,
+ LexicalScope *Scope,
+ SmallVectorImpl<DIE *> &Children) {
+ DIE *ObjectPointer = NULL;
// Collect arguments for current function.
- if (LScopes.isCurrentFunctionScope(Scope))
- for (unsigned i = 0, N = CurrentFnArguments.size(); i < N; ++i)
- if (DbgVariable *ArgDV = CurrentFnArguments[i])
+ if (LScopes.isCurrentFunctionScope(Scope)) {
+ for (DbgVariable *ArgDV : CurrentFnArguments)
+ if (ArgDV)
if (DIE *Arg =
- TheCU->constructVariableDIE(*ArgDV, Scope->isAbstractScope())) {
+ TheCU->constructVariableDIE(*ArgDV, Scope->isAbstractScope())) {
Children.push_back(Arg);
- if (ArgDV->isObjectPointer()) ObjectPointer = Arg;
+ if (ArgDV->isObjectPointer())
+ ObjectPointer = Arg;
}
+ // If this is a variadic function, add an unspecified parameter.
+ DISubprogram SP(Scope->getScopeNode());
+ DIArray FnArgs = SP.getType().getTypeArray();
+ if (FnArgs.getElement(FnArgs.getNumElements() - 1)
+ .isUnspecifiedParameter()) {
+ DIE *Ellipsis = new DIE(dwarf::DW_TAG_unspecified_parameters);
+ Children.push_back(Ellipsis);
+ }
+ }
+
// Collect lexical scope children first.
- const SmallVectorImpl<DbgVariable *> &Variables =ScopeVariables.lookup(Scope);
- for (unsigned i = 0, N = Variables.size(); i < N; ++i)
- if (DIE *Variable =
- TheCU->constructVariableDIE(*Variables[i], Scope->isAbstractScope())) {
+ for (DbgVariable *DV : ScopeVariables.lookup(Scope))
+ if (DIE *Variable = TheCU->constructVariableDIE(*DV,
+ Scope->isAbstractScope())) {
Children.push_back(Variable);
- if (Variables[i]->isObjectPointer()) ObjectPointer = Variable;
+ if (DV->isObjectPointer())
+ ObjectPointer = Variable;
}
- const SmallVectorImpl<LexicalScope *> &Scopes = Scope->getChildren();
- for (unsigned j = 0, M = Scopes.size(); j < M; ++j)
- if (DIE *Nested = constructScopeDIE(TheCU, Scopes[j]))
+ for (LexicalScope *LS : Scope->getChildren())
+ if (DIE *Nested = constructScopeDIE(TheCU, LS))
Children.push_back(Nested);
return ObjectPointer;
}
// Construct a DIE for this scope.
-DIE *DwarfDebug::constructScopeDIE(CompileUnit *TheCU, LexicalScope *Scope) {
+DIE *DwarfDebug::constructScopeDIE(DwarfCompileUnit *TheCU,
+ LexicalScope *Scope) {
if (!Scope || !Scope->getScopeNode())
return NULL;
@@ -634,10 +643,12 @@ DIE *DwarfDebug::constructScopeDIE(CompileUnit *TheCU, LexicalScope *Scope) {
// There is no need to emit empty lexical block DIE.
std::pair<ImportedEntityMap::const_iterator,
- ImportedEntityMap::const_iterator> Range = std::equal_range(
- ScopesWithImportedEntities.begin(), ScopesWithImportedEntities.end(),
- std::pair<const MDNode *, const MDNode *>(DS, (const MDNode*)0),
- less_first());
+ ImportedEntityMap::const_iterator> Range =
+ std::equal_range(
+ ScopesWithImportedEntities.begin(),
+ ScopesWithImportedEntities.end(),
+ std::pair<const MDNode *, const MDNode *>(DS, (const MDNode *)0),
+ less_first());
if (Children.empty() && Range.first == Range.second)
return NULL;
ScopeDIE = constructLexicalScopeDIE(TheCU, Scope);
@@ -657,146 +668,55 @@ DIE *DwarfDebug::constructScopeDIE(CompileUnit *TheCU, LexicalScope *Scope) {
ObjectPointer = createScopeChildrenDIE(TheCU, Scope, Children);
// Add children
- for (SmallVectorImpl<DIE *>::iterator I = Children.begin(),
- E = Children.end(); I != E; ++I)
- ScopeDIE->addChild(*I);
+ for (DIE *I : Children)
+ ScopeDIE->addChild(I);
if (DS.isSubprogram() && ObjectPointer != NULL)
TheCU->addDIEEntry(ScopeDIE, dwarf::DW_AT_object_pointer, ObjectPointer);
- if (DS.isSubprogram())
- TheCU->addPubTypes(DISubprogram(DS));
-
return ScopeDIE;
}
-// Look up the source id with the given directory and source file names.
-// If none currently exists, create a new id and insert it in the
-// SourceIds map. This can update DirectoryNames and SourceFileNames maps
-// as well.
-unsigned DwarfDebug::getOrCreateSourceID(StringRef FileName,
- StringRef DirName, unsigned CUID) {
- // If we use .loc in assembly, we can't separate .file entries according to
- // compile units. Thus all files will belong to the default compile unit.
-
- // FIXME: add a better feature test than hasRawTextSupport. Even better,
- // extend .file to support this.
- if (Asm->TM.hasMCUseLoc() && Asm->OutStreamer.hasRawTextSupport())
- CUID = 0;
-
- // If FE did not provide a file name, then assume stdin.
- if (FileName.empty())
- return getOrCreateSourceID("<stdin>", StringRef(), CUID);
-
- // TODO: this might not belong here. See if we can factor this better.
- if (DirName == CompilationDir)
- DirName = "";
-
- // FileIDCUMap stores the current ID for the given compile unit.
- unsigned SrcId = FileIDCUMap[CUID] + 1;
-
- // We look up the CUID/file/dir by concatenating them with a zero byte.
- SmallString<128> NamePair;
- NamePair += utostr(CUID);
- NamePair += '\0';
- NamePair += DirName;
- NamePair += '\0'; // Zero bytes are not allowed in paths.
- NamePair += FileName;
-
- StringMapEntry<unsigned> &Ent = SourceIdMap.GetOrCreateValue(NamePair, SrcId);
- if (Ent.getValue() != SrcId)
- return Ent.getValue();
-
- FileIDCUMap[CUID] = SrcId;
- // Print out a .file directive to specify files for .loc directives.
- Asm->OutStreamer.EmitDwarfFileDirective(SrcId, DirName, FileName, CUID);
+void DwarfDebug::addGnuPubAttributes(DwarfUnit *U, DIE *D) const {
+ if (!GenerateGnuPubSections)
+ return;
- return SrcId;
+ U->addFlag(D, dwarf::DW_AT_GNU_pubnames);
}
-// Create new CompileUnit for the given metadata node with tag
+// Create new DwarfCompileUnit for the given metadata node with tag
// DW_TAG_compile_unit.
-CompileUnit *DwarfDebug::constructCompileUnit(DICompileUnit DIUnit) {
+DwarfCompileUnit *DwarfDebug::constructDwarfCompileUnit(DICompileUnit DIUnit) {
StringRef FN = DIUnit.getFilename();
CompilationDir = DIUnit.getDirectory();
DIE *Die = new DIE(dwarf::DW_TAG_compile_unit);
- CompileUnit *NewCU = new CompileUnit(GlobalCUIndexCount++, Die, DIUnit, Asm,
- this, &InfoHolder);
+ DwarfCompileUnit *NewCU = new DwarfCompileUnit(
+ InfoHolder.getUnits().size(), Die, DIUnit, Asm, this, &InfoHolder);
+ InfoHolder.addUnit(NewCU);
- FileIDCUMap[NewCU->getUniqueID()] = 0;
- // Call this to emit a .file directive if it wasn't emitted for the source
- // file this CU comes from yet.
- getOrCreateSourceID(FN, CompilationDir, NewCU->getUniqueID());
+ // 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.getContext().setMCLineTableCompilationDir(
+ NewCU->getUniqueID(), CompilationDir);
NewCU->addString(Die, dwarf::DW_AT_producer, DIUnit.getProducer());
NewCU->addUInt(Die, dwarf::DW_AT_language, dwarf::DW_FORM_data2,
DIUnit.getLanguage());
NewCU->addString(Die, dwarf::DW_AT_name, FN);
- // 2.17.1 requires that we use DW_AT_low_pc for a single entry point
- // into an entity. We're using 0 (or a NULL label) for this. For
- // split dwarf it's in the skeleton CU so omit it here.
- if (!useSplitDwarf())
- NewCU->addLabelAddress(Die, dwarf::DW_AT_low_pc, NULL);
-
- // Define start line table label for each Compile Unit.
- MCSymbol *LineTableStartSym = Asm->GetTempSymbol("line_table_start",
- NewCU->getUniqueID());
- Asm->OutStreamer.getContext().setMCLineTableSymbol(LineTableStartSym,
- NewCU->getUniqueID());
-
- // Use a single line table if we are using .loc and generating assembly.
- bool UseTheFirstCU =
- (Asm->TM.hasMCUseLoc() && Asm->OutStreamer.hasRawTextSupport()) ||
- (NewCU->getUniqueID() == 0);
-
if (!useSplitDwarf()) {
- // DW_AT_stmt_list is a offset of line number information for this
- // compile unit in debug_line section. For split dwarf this is
- // left in the skeleton CU and so not included.
- // The line table entries are not always emitted in assembly, so it
- // is not okay to use line_table_start here.
- if (Asm->MAI->doesDwarfUseRelocationsAcrossSections())
- NewCU->addLabel(Die, dwarf::DW_AT_stmt_list, dwarf::DW_FORM_sec_offset,
- UseTheFirstCU ? Asm->GetTempSymbol("section_line")
- : LineTableStartSym);
- else if (UseTheFirstCU)
- NewCU->addUInt(Die, dwarf::DW_AT_stmt_list, dwarf::DW_FORM_data4, 0);
- else
- NewCU->addDelta(Die, dwarf::DW_AT_stmt_list, dwarf::DW_FORM_data4,
- LineTableStartSym, DwarfLineSectionSym);
+ NewCU->initStmtList(DwarfLineSectionSym);
// If we're using split dwarf the compilation dir is going to be in the
// skeleton CU and so we don't need to duplicate it here.
if (!CompilationDir.empty())
NewCU->addString(Die, dwarf::DW_AT_comp_dir, CompilationDir);
- // Flags to let the linker know we have emitted new style pubnames. Only
- // emit it here if we don't have a skeleton CU for split dwarf.
- if (GenerateGnuPubSections) {
- if (Asm->MAI->doesDwarfUseRelocationsAcrossSections())
- NewCU->addLabel(Die, dwarf::DW_AT_GNU_pubnames,
- dwarf::DW_FORM_sec_offset,
- Asm->GetTempSymbol("gnu_pubnames",
- NewCU->getUniqueID()));
- else
- NewCU->addDelta(Die, dwarf::DW_AT_GNU_pubnames, dwarf::DW_FORM_data4,
- Asm->GetTempSymbol("gnu_pubnames",
- NewCU->getUniqueID()),
- DwarfGnuPubNamesSectionSym);
-
- if (Asm->MAI->doesDwarfUseRelocationsAcrossSections())
- NewCU->addLabel(Die, dwarf::DW_AT_GNU_pubtypes,
- dwarf::DW_FORM_sec_offset,
- Asm->GetTempSymbol("gnu_pubtypes",
- NewCU->getUniqueID()));
- else
- NewCU->addDelta(Die, dwarf::DW_AT_GNU_pubtypes, dwarf::DW_FORM_data4,
- Asm->GetTempSymbol("gnu_pubtypes",
- NewCU->getUniqueID()),
- DwarfGnuPubTypesSectionSym);
- }
+ addGnuPubAttributes(NewCU, Die);
}
if (DIUnit.isOptimized())
@@ -808,12 +728,18 @@ CompileUnit *DwarfDebug::constructCompileUnit(DICompileUnit DIUnit) {
if (unsigned RVer = DIUnit.getRunTimeVersion())
NewCU->addUInt(Die, dwarf::DW_AT_APPLE_major_runtime_vers,
- dwarf::DW_FORM_data1, RVer);
+ dwarf::DW_FORM_data1, RVer);
if (!FirstCU)
FirstCU = NewCU;
- InfoHolder.addUnit(NewCU);
+ if (useSplitDwarf()) {
+ NewCU->initSection(Asm->getObjFileLowering().getDwarfInfoDWOSection(),
+ DwarfInfoDWOSectionSym);
+ NewCU->setSkeleton(constructSkeletonCU(NewCU));
+ } else
+ NewCU->initSection(Asm->getObjFileLowering().getDwarfInfoSection(),
+ DwarfInfoSectionSym);
CUMap.insert(std::make_pair(DIUnit, NewCU));
CUDieMap.insert(std::make_pair(Die, NewCU));
@@ -821,12 +747,13 @@ CompileUnit *DwarfDebug::constructCompileUnit(DICompileUnit DIUnit) {
}
// Construct subprogram DIE.
-void DwarfDebug::constructSubprogramDIE(CompileUnit *TheCU, const MDNode *N) {
+void DwarfDebug::constructSubprogramDIE(DwarfCompileUnit *TheCU,
+ const MDNode *N) {
// FIXME: We should only call this routine once, however, during LTO if a
// program is defined in multiple CUs we could end up calling it out of
// beginModule as we walk the CUs.
- CompileUnit *&CURef = SPMap[N];
+ DwarfCompileUnit *&CURef = SPMap[N];
if (CURef)
return;
CURef = TheCU;
@@ -843,24 +770,22 @@ void DwarfDebug::constructSubprogramDIE(CompileUnit *TheCU, const MDNode *N) {
TheCU->addGlobalName(SP.getName(), SubprogramDie, resolve(SP.getContext()));
}
-void DwarfDebug::constructImportedEntityDIE(CompileUnit *TheCU,
+void DwarfDebug::constructImportedEntityDIE(DwarfCompileUnit *TheCU,
const MDNode *N) {
DIImportedEntity Module(N);
- if (!Module.Verify())
- return;
+ assert(Module.Verify());
if (DIE *D = TheCU->getOrCreateContextDIE(Module.getContext()))
constructImportedEntityDIE(TheCU, Module, D);
}
-void DwarfDebug::constructImportedEntityDIE(CompileUnit *TheCU, const MDNode *N,
- DIE *Context) {
+void DwarfDebug::constructImportedEntityDIE(DwarfCompileUnit *TheCU,
+ const MDNode *N, DIE *Context) {
DIImportedEntity Module(N);
- if (!Module.Verify())
- return;
+ assert(Module.Verify());
return constructImportedEntityDIE(TheCU, Module, Context);
}
-void DwarfDebug::constructImportedEntityDIE(CompileUnit *TheCU,
+void DwarfDebug::constructImportedEntityDIE(DwarfCompileUnit *TheCU,
const DIImportedEntity &Module,
DIE *Context) {
assert(Module.Verify() &&
@@ -869,7 +794,7 @@ void DwarfDebug::constructImportedEntityDIE(CompileUnit *TheCU,
DIE *IMDie = new DIE(Module.getTag());
TheCU->insertDIE(Module, IMDie);
DIE *EntityDie;
- DIDescriptor Entity = Module.getEntity();
+ DIDescriptor Entity = resolve(Module.getEntity());
if (Entity.isNameSpace())
EntityDie = TheCU->getOrCreateNameSpace(DINameSpace(Entity));
else if (Entity.isSubprogram())
@@ -878,11 +803,9 @@ void DwarfDebug::constructImportedEntityDIE(CompileUnit *TheCU,
EntityDie = TheCU->getOrCreateTypeDIE(DIType(Entity));
else
EntityDie = TheCU->getDIE(Entity);
- unsigned FileID = getOrCreateSourceID(Module.getContext().getFilename(),
- Module.getContext().getDirectory(),
- TheCU->getUniqueID());
- TheCU->addUInt(IMDie, dwarf::DW_AT_decl_file, None, FileID);
- TheCU->addUInt(IMDie, dwarf::DW_AT_decl_line, None, Module.getLineNumber());
+ TheCU->addSourceLine(IMDie, Module.getLineNumber(),
+ Module.getContext().getFilename(),
+ Module.getContext().getDirectory());
TheCU->addDIEEntry(IMDie, dwarf::DW_AT_import, EntityDie);
StringRef Name = Module.getName();
if (!Name.empty())
@@ -909,9 +832,11 @@ void DwarfDebug::beginModule() {
// Emit initial sections so we can reference labels later.
emitSectionLabels();
- for (unsigned i = 0, e = CU_Nodes->getNumOperands(); i != e; ++i) {
- DICompileUnit CUNode(CU_Nodes->getOperand(i));
- CompileUnit *CU = constructCompileUnit(CUNode);
+ SingleCU = CU_Nodes->getNumOperands() == 1;
+
+ for (MDNode *N : CU_Nodes->operands()) {
+ DICompileUnit CUNode(N);
+ DwarfCompileUnit *CU = constructDwarfCompileUnit(CUNode);
DIArray ImportedEntities = CUNode.getImportedEntities();
for (unsigned i = 0, e = ImportedEntities.getNumElements(); i != e; ++i)
ScopesWithImportedEntities.push_back(std::make_pair(
@@ -929,8 +854,13 @@ void DwarfDebug::beginModule() {
for (unsigned i = 0, e = EnumTypes.getNumElements(); i != e; ++i)
CU->getOrCreateTypeDIE(EnumTypes.getElement(i));
DIArray RetainedTypes = CUNode.getRetainedTypes();
- for (unsigned i = 0, e = RetainedTypes.getNumElements(); i != e; ++i)
- CU->getOrCreateTypeDIE(RetainedTypes.getElement(i));
+ for (unsigned i = 0, e = RetainedTypes.getNumElements(); i != e; ++i) {
+ DIType Ty(RetainedTypes.getElement(i));
+ // The retained types array by design contains pointers to
+ // MDNodes rather than DIRefs. Unique them here.
+ DIType UniqueTy(resolve(Ty.getRef()));
+ CU->getOrCreateTypeDIE(UniqueTy);
+ }
// Emit imported_modules last so that the relevant context is already
// available.
for (unsigned i = 0, e = ImportedEntities.getNumElements(); i != e; ++i)
@@ -947,14 +877,11 @@ void DwarfDebug::beginModule() {
// Attach DW_AT_inline attribute with inlined subprogram DIEs.
void DwarfDebug::computeInlinedDIEs() {
// Attach DW_AT_inline attribute with inlined subprogram DIEs.
- for (SmallPtrSet<DIE *, 4>::iterator AI = InlinedSubprogramDIEs.begin(),
- AE = InlinedSubprogramDIEs.end(); AI != AE; ++AI) {
- DIE *ISP = *AI;
+ for (DIE *ISP : InlinedSubprogramDIEs)
FirstCU->addUInt(ISP, dwarf::DW_AT_inline, None, dwarf::DW_INL_inlined);
- }
- for (DenseMap<const MDNode *, DIE *>::iterator AI = AbstractSPDies.begin(),
- AE = AbstractSPDies.end(); AI != AE; ++AI) {
- DIE *ISP = AI->second;
+
+ for (const auto &AI : AbstractSPDies) {
+ DIE *ISP = AI.second;
if (InlinedSubprogramDIEs.count(ISP))
continue;
FirstCU->addUInt(ISP, dwarf::DW_AT_inline, None, dwarf::DW_INL_inlined);
@@ -966,8 +893,8 @@ void DwarfDebug::collectDeadVariables() {
const Module *M = MMI->getModule();
if (NamedMDNode *CU_Nodes = M->getNamedMetadata("llvm.dbg.cu")) {
- for (unsigned i = 0, e = CU_Nodes->getNumOperands(); i != e; ++i) {
- DICompileUnit TheCU(CU_Nodes->getOperand(i));
+ for (MDNode *N : CU_Nodes->operands()) {
+ DICompileUnit TheCU(N);
DIArray Subprograms = TheCU.getSubprograms();
for (unsigned i = 0, e = Subprograms.getNumElements(); i != e; ++i) {
DISubprogram SP(Subprograms.getElement(i));
@@ -982,7 +909,8 @@ void DwarfDebug::collectDeadVariables() {
continue;
// Construct subprogram DIE and add variables DIEs.
- CompileUnit *SPCU = CUMap.lookup(TheCU);
+ DwarfCompileUnit *SPCU =
+ static_cast<DwarfCompileUnit *>(CUMap.lookup(TheCU));
assert(SPCU && "Unable to find Compile Unit!");
// FIXME: See the comment in constructSubprogramDIE about duplicate
// subprogram DIEs.
@@ -993,8 +921,7 @@ void DwarfDebug::collectDeadVariables() {
if (!DV.isVariable())
continue;
DbgVariable NewVar(DV, NULL, this);
- if (DIE *VariableDIE =
- SPCU->constructVariableDIE(NewVar, false))
+ if (DIE *VariableDIE = SPCU->constructVariableDIE(NewVar, false))
SPDIE->addChild(VariableDIE);
}
}
@@ -1002,41 +929,6 @@ void DwarfDebug::collectDeadVariables() {
}
}
-// Type Signature [7.27] and ODR Hash code.
-
-/// \brief Grabs the string in whichever attribute is passed in and returns
-/// a reference to it. Returns "" if the attribute doesn't exist.
-static StringRef getDIEStringAttr(DIE *Die, unsigned Attr) {
- DIEValue *V = Die->findAttribute(Attr);
-
- if (DIEString *S = dyn_cast_or_null<DIEString>(V))
- return S->getString();
-
- return StringRef("");
-}
-
-/// Return true if the current DIE is contained within an anonymous namespace.
-static bool isContainedInAnonNamespace(DIE *Die) {
- DIE *Parent = Die->getParent();
-
- while (Parent) {
- if (Parent->getTag() == dwarf::DW_TAG_namespace &&
- getDIEStringAttr(Parent, dwarf::DW_AT_name) == "")
- return true;
- Parent = Parent->getParent();
- }
-
- return false;
-}
-
-/// Test if the current CU language is C++ and that we have
-/// a named type that is not contained in an anonymous namespace.
-static bool shouldAddODRHash(CompileUnit *CU, DIE *Die) {
- return CU->getLanguage() == dwarf::DW_LANG_C_plus_plus &&
- getDIEStringAttr(Die, dwarf::DW_AT_name) != "" &&
- !isContainedInAnonNamespace(Die);
-}
-
void DwarfDebug::finalizeModuleInfo() {
// Collect info for variables that were optimized out.
collectDeadVariables();
@@ -1044,47 +936,67 @@ void DwarfDebug::finalizeModuleInfo() {
// Attach DW_AT_inline attribute with inlined subprogram DIEs.
computeInlinedDIEs();
- // Split out type units and conditionally add an ODR tag to the split
- // out type.
- // FIXME: Do type splitting.
- for (unsigned i = 0, e = TypeUnits.size(); i != e; ++i) {
- DIE *Die = TypeUnits[i];
- DIEHash Hash;
- // If we've requested ODR hashes and it's applicable for an ODR hash then
- // add the ODR signature now.
- // FIXME: This should be added onto the type unit, not the type, but this
- // works as an intermediate stage.
- if (GenerateODRHash && shouldAddODRHash(CUMap.begin()->second, Die))
- CUMap.begin()->second->addUInt(Die, dwarf::DW_AT_GNU_odr_signature,
- dwarf::DW_FORM_data8,
- Hash.computeDIEODRSignature(*Die));
- }
-
- // Handle anything that needs to be done on a per-cu basis.
- for (DenseMap<const MDNode *, CompileUnit *>::iterator CUI = CUMap.begin(),
- CUE = CUMap.end();
- CUI != CUE; ++CUI) {
- CompileUnit *TheCU = CUI->second;
+ // Handle anything that needs to be done on a per-unit basis after
+ // all other generation.
+ for (DwarfUnit *TheU : getUnits()) {
// Emit DW_AT_containing_type attribute to connect types with their
// vtable holding type.
- TheCU->constructContainingTypeDIEs();
-
- // If we're splitting the dwarf out now that we've got the entire
- // CU then construct a skeleton CU based upon it.
- if (useSplitDwarf()) {
- uint64_t ID = 0;
- if (GenerateCUHash) {
- DIEHash CUHash;
- ID = CUHash.computeCUSignature(*TheCU->getCUDie());
+ TheU->constructContainingTypeDIEs();
+
+ // Add CU specific attributes if we need to add any.
+ if (TheU->getUnitDie()->getTag() == dwarf::DW_TAG_compile_unit) {
+ // If we're splitting the dwarf out now that we've got the entire
+ // CU then add the dwo id to it.
+ DwarfCompileUnit *SkCU =
+ static_cast<DwarfCompileUnit *>(TheU->getSkeleton());
+ if (useSplitDwarf()) {
+ // Emit a unique identifier for this CU.
+ uint64_t ID = DIEHash(Asm).computeCUSignature(*TheU->getUnitDie());
+ TheU->addUInt(TheU->getUnitDie(), dwarf::DW_AT_GNU_dwo_id,
+ dwarf::DW_FORM_data8, ID);
+ SkCU->addUInt(SkCU->getUnitDie(), dwarf::DW_AT_GNU_dwo_id,
+ dwarf::DW_FORM_data8, ID);
+
+ // We don't keep track of which addresses are used in which CU so this
+ // is a bit pessimistic under LTO.
+ if (!InfoHolder.getAddrPool()->empty())
+ addSectionLabel(Asm, SkCU, SkCU->getUnitDie(),
+ dwarf::DW_AT_GNU_addr_base, DwarfAddrSectionSym,
+ DwarfAddrSectionSym);
+ if (!TheU->getRangeLists().empty())
+ addSectionLabel(Asm, SkCU, SkCU->getUnitDie(),
+ dwarf::DW_AT_GNU_ranges_base,
+ DwarfDebugRangeSectionSym, DwarfDebugRangeSectionSym);
+ }
+
+ // If we have code split among multiple sections or non-contiguous
+ // ranges of code then emit a DW_AT_ranges attribute on the unit that will
+ // remain in the .o file, otherwise add a DW_AT_low_pc.
+ // FIXME: We should use ranges allow reordering of code ala
+ // .subsections_via_symbols in mach-o. This would mean turning on
+ // ranges for all subprogram DIEs for mach-o.
+ DwarfCompileUnit *U = SkCU ? SkCU : static_cast<DwarfCompileUnit *>(TheU);
+ unsigned NumRanges = TheU->getRanges().size();
+ if (NumRanges) {
+ if (NumRanges > 1) {
+ addSectionLabel(Asm, U, U->getUnitDie(), dwarf::DW_AT_ranges,
+ Asm->GetTempSymbol("cu_ranges", U->getUniqueID()),
+ DwarfDebugRangeSectionSym);
+
+ // A DW_AT_low_pc attribute may also be specified in combination with
+ // DW_AT_ranges to specify the default base address for use in
+ // location lists (see Section 2.6.2) and range lists (see Section
+ // 2.17.3).
+ U->addUInt(U->getUnitDie(), dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr,
+ 0);
+ } else {
+ RangeSpan &Range = TheU->getRanges().back();
+ U->addLocalLabelAddress(U->getUnitDie(), dwarf::DW_AT_low_pc,
+ Range.getStart());
+ U->addLabelDelta(U->getUnitDie(), dwarf::DW_AT_high_pc,
+ Range.getEnd(), Range.getStart());
+ }
}
- // This should be a unique identifier when we want to build .dwp files.
- TheCU->addUInt(TheCU->getCUDie(), dwarf::DW_AT_GNU_dwo_id,
- dwarf::DW_FORM_data8, ID);
- // Now construct the skeleton CU associated.
- CompileUnit *SkCU = constructSkeletonCU(TheCU);
- // This should be a unique identifier when we want to build .dwp files.
- SkCU->addUInt(SkCU->getCUDie(), dwarf::DW_AT_GNU_dwo_id,
- dwarf::DW_FORM_data8, ID);
}
}
@@ -1095,9 +1007,8 @@ void DwarfDebug::finalizeModuleInfo() {
}
void DwarfDebug::endSections() {
- // Filter labels by section.
- for (size_t n = 0; n < ArangeLabels.size(); n++) {
- const SymbolCU &SCU = ArangeLabels[n];
+ // Filter labels by section.
+ for (const SymbolCU &SCU : ArangeLabels) {
if (SCU.Sym->isInSection()) {
// Make a note of this symbol and it's section.
const MCSection *Section = &SCU.Sym->getSection();
@@ -1113,9 +1024,8 @@ void DwarfDebug::endSections() {
// Build a list of sections used.
std::vector<const MCSection *> Sections;
- for (SectionMapType::iterator it = SectionMap.begin(); it != SectionMap.end();
- it++) {
- const MCSection *Section = it->first;
+ for (const auto &it : SectionMap) {
+ const MCSection *Section = it.first;
Sections.push_back(Section);
}
@@ -1124,15 +1034,15 @@ void DwarfDebug::endSections() {
std::sort(Sections.begin(), Sections.end(), SectionSort);
// Add terminating symbols for each section.
- for (unsigned ID=0;ID<Sections.size();ID++) {
+ for (unsigned ID = 0, E = Sections.size(); ID != E; ID++) {
const MCSection *Section = Sections[ID];
MCSymbol *Sym = NULL;
if (Section) {
// We can't call MCSection::getLabelEndName, as it's only safe to do so
- // if we know the section name up-front. For user-created sections, the resulting
- // label may not be valid to use as a label. (section names can use a greater
- // set of characters on some systems)
+ // if we know the section name up-front. For user-created sections, the
+ // resulting label may not be valid to use as a label. (section names can
+ // use a greater set of characters on some systems)
Sym = Asm->GetTempSymbol("debug_end", ID);
Asm->OutStreamer.SwitchSection(Section);
Asm->OutStreamer.EmitLabel(Sym);
@@ -1145,8 +1055,11 @@ void DwarfDebug::endSections() {
// Emit all Dwarf sections that should come after the content.
void DwarfDebug::endModule() {
+ assert(CurFn == 0);
+ assert(CurMI == 0);
- if (!FirstCU) return;
+ if (!FirstCU)
+ return;
// End any existing sections.
// TODO: Does this need to happen?
@@ -1155,58 +1068,32 @@ void DwarfDebug::endModule() {
// Finalize the debug info for the module.
finalizeModuleInfo();
- if (!useSplitDwarf()) {
- emitDebugStr();
+ emitDebugStr();
- // Emit all the DIEs into a debug info section.
- emitDebugInfo();
+ // Emit all the DIEs into a debug info section.
+ emitDebugInfo();
- // Corresponding abbreviations into a abbrev section.
- emitAbbreviations();
-
- // Emit info into a debug loc section.
- emitDebugLoc();
+ // Corresponding abbreviations into a abbrev section.
+ emitAbbreviations();
- // Emit info into a debug aranges section.
+ // Emit info into a debug aranges section.
+ if (GenerateARangeSection)
emitDebugARanges();
- // Emit info into a debug ranges section.
- emitDebugRanges();
-
- // Emit info into a debug macinfo section.
- emitDebugMacInfo();
+ // Emit info into a debug ranges section.
+ emitDebugRanges();
- } else {
- // TODO: Fill this in for separated debug sections and separate
- // out information into new sections.
- emitDebugStr();
- if (useSplitDwarf())
- emitDebugStrDWO();
-
- // Emit the debug info section and compile units.
- emitDebugInfo();
+ if (useSplitDwarf()) {
+ emitDebugStrDWO();
emitDebugInfoDWO();
-
- // Corresponding abbreviations into a abbrev section.
- emitAbbreviations();
emitDebugAbbrevDWO();
-
- // Emit info into a debug loc section.
- emitDebugLoc();
-
- // Emit info into a debug aranges section.
- emitDebugARanges();
-
- // Emit info into a debug ranges section.
- emitDebugRanges();
-
- // Emit info into a debug macinfo section.
- emitDebugMacInfo();
-
+ emitDebugLineDWO();
// Emit DWO addresses.
InfoHolder.emitAddresses(Asm->getObjFileLowering().getDwarfAddrSection());
-
- }
+ emitDebugLocDWO();
+ } else
+ // Emit info into a debug loc section.
+ emitDebugLoc();
// Emit info into the dwarf accelerator table sections.
if (useDwarfAccelTables()) {
@@ -1224,13 +1111,6 @@ void DwarfDebug::endModule() {
// clean up.
SPMap.clear();
- for (DenseMap<const MDNode *, CompileUnit *>::iterator I = CUMap.begin(),
- E = CUMap.end(); I != E; ++I)
- delete I->second;
-
- for (SmallVectorImpl<CompileUnit *>::iterator I = SkeletonCUs.begin(),
- E = SkeletonCUs.end(); I != E; ++I)
- delete *I;
// Reset these for the next Module if we have one.
FirstCU = NULL;
@@ -1257,8 +1137,7 @@ DbgVariable *DwarfDebug::findAbstractVariable(DIVariable &DV,
}
// If Var is a current function argument then add it to CurrentFnArguments list.
-bool DwarfDebug::addCurrentFnArgument(const MachineFunction *MF,
- DbgVariable *Var, LexicalScope *Scope) {
+bool DwarfDebug::addCurrentFnArgument(DbgVariable *Var, LexicalScope *Scope) {
if (!LScopes.isCurrentFunctionScope(Scope))
return false;
DIVariable DV = Var->getVariable();
@@ -1270,7 +1149,7 @@ bool DwarfDebug::addCurrentFnArgument(const MachineFunction *MF,
size_t Size = CurrentFnArguments.size();
if (Size == 0)
- CurrentFnArguments.resize(MF->getFunction()->arg_size());
+ CurrentFnArguments.resize(CurFn->getFunction()->arg_size());
// llvm::Function argument size is not good indicator of how many
// arguments does the function have at source level.
if (ArgNo > Size)
@@ -1280,31 +1159,26 @@ bool DwarfDebug::addCurrentFnArgument(const MachineFunction *MF,
}
// Collect variable information from side table maintained by MMI.
-void
-DwarfDebug::collectVariableInfoFromMMITable(const MachineFunction *MF,
- SmallPtrSet<const MDNode *, 16> &Processed) {
- MachineModuleInfo::VariableDbgInfoMapTy &VMap = MMI->getVariableDbgInfo();
- for (MachineModuleInfo::VariableDbgInfoMapTy::iterator VI = VMap.begin(),
- VE = VMap.end(); VI != VE; ++VI) {
- const MDNode *Var = VI->first;
- if (!Var) continue;
- Processed.insert(Var);
- DIVariable DV(Var);
- const std::pair<unsigned, DebugLoc> &VP = VI->second;
-
- LexicalScope *Scope = LScopes.findLexicalScope(VP.second);
+void DwarfDebug::collectVariableInfoFromMMITable(
+ SmallPtrSet<const MDNode *, 16> &Processed) {
+ for (const auto &VI : MMI->getVariableDbgInfo()) {
+ if (!VI.Var)
+ continue;
+ Processed.insert(VI.Var);
+ DIVariable DV(VI.Var);
+ LexicalScope *Scope = LScopes.findLexicalScope(VI.Loc);
// If variable scope is not found then skip this variable.
if (Scope == 0)
continue;
- DbgVariable *AbsDbgVariable = findAbstractVariable(DV, VP.second);
+ DbgVariable *AbsDbgVariable = findAbstractVariable(DV, VI.Loc);
DbgVariable *RegVar = new DbgVariable(DV, AbsDbgVariable, this);
- RegVar->setFrameIndex(VP.first);
- if (!addCurrentFnArgument(MF, RegVar, Scope))
+ RegVar->setFrameIndex(VI.Slot);
+ if (!addCurrentFnArgument(RegVar, Scope))
addScopeVariable(Scope, RegVar);
if (AbsDbgVariable)
- AbsDbgVariable->setFrameIndex(VP.first);
+ AbsDbgVariable->setFrameIndex(VI.Slot);
}
}
@@ -1312,18 +1186,19 @@ DwarfDebug::collectVariableInfoFromMMITable(const MachineFunction *MF,
// defined reg.
static bool isDbgValueInDefinedReg(const MachineInstr *MI) {
assert(MI->isDebugValue() && "Invalid DBG_VALUE machine instruction!");
- return MI->getNumOperands() == 3 &&
- MI->getOperand(0).isReg() && MI->getOperand(0).getReg() &&
+ return MI->getNumOperands() == 3 && MI->getOperand(0).isReg() &&
+ MI->getOperand(0).getReg() &&
(MI->getOperand(1).isImm() ||
(MI->getOperand(1).isReg() && MI->getOperand(1).getReg() == 0U));
}
// Get .debug_loc entry for the instruction range starting at MI.
-static DotDebugLocEntry getDebugLocEntry(AsmPrinter *Asm,
- const MCSymbol *FLabel,
- const MCSymbol *SLabel,
- const MachineInstr *MI) {
- const MDNode *Var = MI->getOperand(MI->getNumOperands() - 1).getMetadata();
+static DebugLocEntry getDebugLocEntry(AsmPrinter *Asm,
+ const MCSymbol *FLabel,
+ const MCSymbol *SLabel,
+ const MachineInstr *MI,
+ DwarfCompileUnit *Unit) {
+ const MDNode *Var = MI->getOperand(MI->getNumOperands() - 1).getMetadata();
assert(MI->getNumOperands() == 3);
if (MI->getOperand(0).isReg()) {
@@ -1334,36 +1209,32 @@ static DotDebugLocEntry getDebugLocEntry(AsmPrinter *Asm,
MLoc.set(MI->getOperand(0).getReg());
else
MLoc.set(MI->getOperand(0).getReg(), MI->getOperand(1).getImm());
- return DotDebugLocEntry(FLabel, SLabel, MLoc, Var);
+ return DebugLocEntry(FLabel, SLabel, MLoc, Var, Unit);
}
if (MI->getOperand(0).isImm())
- return DotDebugLocEntry(FLabel, SLabel, MI->getOperand(0).getImm());
+ return DebugLocEntry(FLabel, SLabel, MI->getOperand(0).getImm(), Unit);
if (MI->getOperand(0).isFPImm())
- return DotDebugLocEntry(FLabel, SLabel, MI->getOperand(0).getFPImm());
+ return DebugLocEntry(FLabel, SLabel, MI->getOperand(0).getFPImm(), Unit);
if (MI->getOperand(0).isCImm())
- return DotDebugLocEntry(FLabel, SLabel, MI->getOperand(0).getCImm());
+ return DebugLocEntry(FLabel, SLabel, MI->getOperand(0).getCImm(), Unit);
llvm_unreachable("Unexpected 3 operand DBG_VALUE instruction!");
}
// Find variables for each lexical scope.
void
-DwarfDebug::collectVariableInfo(const MachineFunction *MF,
- SmallPtrSet<const MDNode *, 16> &Processed) {
+DwarfDebug::collectVariableInfo(SmallPtrSet<const MDNode *, 16> &Processed) {
// Grab the variable info that was squirreled away in the MMI side-table.
- collectVariableInfoFromMMITable(MF, Processed);
+ collectVariableInfoFromMMITable(Processed);
- for (SmallVectorImpl<const MDNode*>::const_iterator
- UVI = UserVariables.begin(), UVE = UserVariables.end(); UVI != UVE;
- ++UVI) {
- const MDNode *Var = *UVI;
+ for (const MDNode *Var : UserVariables) {
if (Processed.count(Var))
continue;
// History contains relevant DBG_VALUE instructions for Var and instructions
// clobbering it.
- SmallVectorImpl<const MachineInstr*> &History = DbgValues[Var];
+ SmallVectorImpl<const MachineInstr *> &History = DbgValues[Var];
if (History.empty())
continue;
const MachineInstr *MInsn = History.front();
@@ -1371,7 +1242,7 @@ DwarfDebug::collectVariableInfo(const MachineFunction *MF,
DIVariable DV(Var);
LexicalScope *Scope = NULL;
if (DV.getTag() == dwarf::DW_TAG_arg_variable &&
- DISubprogram(DV.getContext()).describes(MF->getFunction()))
+ DISubprogram(DV.getContext()).describes(CurFn->getFunction()))
Scope = LScopes.getCurrentFunctionScope();
else if (MDNode *IA = DV.getInlinedAt())
Scope = LScopes.findInlinedScope(DebugLoc::getFromDILocation(IA));
@@ -1385,14 +1256,14 @@ DwarfDebug::collectVariableInfo(const MachineFunction *MF,
assert(MInsn->isDebugValue() && "History must begin with debug value");
DbgVariable *AbsVar = findAbstractVariable(DV, MInsn->getDebugLoc());
DbgVariable *RegVar = new DbgVariable(DV, AbsVar, this);
- if (!addCurrentFnArgument(MF, RegVar, Scope))
+ if (!addCurrentFnArgument(RegVar, Scope))
addScopeVariable(Scope, RegVar);
if (AbsVar)
AbsVar->setMInsn(MInsn);
// Simplify ranges that are fully coalesced.
- if (History.size() <= 1 || (History.size() == 2 &&
- MInsn->isIdenticalTo(History.back()))) {
+ if (History.size() <= 1 ||
+ (History.size() == 2 && MInsn->isIdenticalTo(History.back()))) {
RegVar->setMInsn(MInsn);
continue;
}
@@ -1400,14 +1271,21 @@ DwarfDebug::collectVariableInfo(const MachineFunction *MF,
// Handle multiple DBG_VALUE instructions describing one variable.
RegVar->setDotDebugLocOffset(DotDebugLocEntries.size());
- for (SmallVectorImpl<const MachineInstr*>::const_iterator
- HI = History.begin(), HE = History.end(); HI != HE; ++HI) {
+ DotDebugLocEntries.resize(DotDebugLocEntries.size() + 1);
+ DebugLocList &LocList = DotDebugLocEntries.back();
+ LocList.Label =
+ Asm->GetTempSymbol("debug_loc", DotDebugLocEntries.size() - 1);
+ SmallVector<DebugLocEntry, 4> &DebugLoc = LocList.List;
+ for (SmallVectorImpl<const MachineInstr *>::const_iterator
+ HI = History.begin(),
+ HE = History.end();
+ HI != HE; ++HI) {
const MachineInstr *Begin = *HI;
assert(Begin->isDebugValue() && "Invalid History entry");
// Check if DBG_VALUE is truncating a range.
- if (Begin->getNumOperands() > 1 && Begin->getOperand(0).isReg()
- && !Begin->getOperand(0).getReg())
+ if (Begin->getNumOperands() > 1 && Begin->getOperand(0).isReg() &&
+ !Begin->getOperand(0).getReg())
continue;
// Compute the range for a register location.
@@ -1421,7 +1299,7 @@ DwarfDebug::collectVariableInfo(const MachineFunction *MF,
else {
const MachineInstr *End = HI[1];
DEBUG(dbgs() << "DotDebugLoc Pair:\n"
- << "\t" << *Begin << "\t" << *End << "\n");
+ << "\t" << *Begin << "\t" << *End << "\n");
if (End->isDebugValue())
SLabel = getLabelBeforeInsn(End);
else {
@@ -1433,10 +1311,12 @@ DwarfDebug::collectVariableInfo(const MachineFunction *MF,
}
// The value is valid until the next DBG_VALUE or clobber.
- DotDebugLocEntries.push_back(getDebugLocEntry(Asm, FLabel, SLabel,
- Begin));
+ LexicalScope *FnScope = LScopes.getCurrentFunctionScope();
+ DwarfCompileUnit *TheCU = SPMap.lookup(FnScope->getScopeNode());
+ DebugLocEntry Loc = getDebugLocEntry(Asm, FLabel, SLabel, Begin, TheCU);
+ if (DebugLoc.empty() || !DebugLoc.back().Merge(Loc))
+ DebugLoc.push_back(std::move(Loc));
}
- DotDebugLocEntries.push_back(DotDebugLocEntry());
}
// Collect info for variables that were optimized out.
@@ -1465,6 +1345,8 @@ MCSymbol *DwarfDebug::getLabelAfterInsn(const MachineInstr *MI) {
// Process beginning of an instruction.
void DwarfDebug::beginInstruction(const MachineInstr *MI) {
+ assert(CurMI == 0);
+ CurMI = MI;
// Check if source location changes, but ignore DBG_VALUE locations.
if (!MI->isDebugValue()) {
DebugLoc DL = MI->getDebugLoc();
@@ -1487,8 +1369,8 @@ void DwarfDebug::beginInstruction(const MachineInstr *MI) {
}
// Insert labels where requested.
- DenseMap<const MachineInstr*, MCSymbol*>::iterator I =
- LabelsBeforeInsn.find(MI);
+ DenseMap<const MachineInstr *, MCSymbol *>::iterator I =
+ LabelsBeforeInsn.find(MI);
// No label needed.
if (I == LabelsBeforeInsn.end())
@@ -1506,14 +1388,16 @@ void DwarfDebug::beginInstruction(const MachineInstr *MI) {
}
// Process end of an instruction.
-void DwarfDebug::endInstruction(const MachineInstr *MI) {
+void DwarfDebug::endInstruction() {
+ assert(CurMI != 0);
// Don't create a new label after DBG_VALUE instructions.
// They don't generate code.
- if (!MI->isDebugValue())
+ if (!CurMI->isDebugValue())
PrevLabel = 0;
- DenseMap<const MachineInstr*, MCSymbol*>::iterator I =
- LabelsAfterInsn.find(MI);
+ DenseMap<const MachineInstr *, MCSymbol *>::iterator I =
+ LabelsAfterInsn.find(CurMI);
+ CurMI = 0;
// No label needed.
if (I == LabelsAfterInsn.end())
@@ -1543,53 +1427,24 @@ void DwarfDebug::identifyScopeMarkers() {
const SmallVectorImpl<LexicalScope *> &Children = S->getChildren();
if (!Children.empty())
- for (SmallVectorImpl<LexicalScope *>::const_iterator SI = Children.begin(),
- SE = Children.end(); SI != SE; ++SI)
- WorkList.push_back(*SI);
+ WorkList.append(Children.begin(), Children.end());
if (S->isAbstractScope())
continue;
- const SmallVectorImpl<InsnRange> &Ranges = S->getRanges();
- if (Ranges.empty())
- continue;
- for (SmallVectorImpl<InsnRange>::const_iterator RI = Ranges.begin(),
- RE = Ranges.end(); RI != RE; ++RI) {
- assert(RI->first && "InsnRange does not have first instruction!");
- assert(RI->second && "InsnRange does not have second instruction!");
- requestLabelBeforeInsn(RI->first);
- requestLabelAfterInsn(RI->second);
+ for (const InsnRange &R : S->getRanges()) {
+ assert(R.first && "InsnRange does not have first instruction!");
+ assert(R.second && "InsnRange does not have second instruction!");
+ requestLabelBeforeInsn(R.first);
+ requestLabelAfterInsn(R.second);
}
}
}
-// Get MDNode for DebugLoc's scope.
-static MDNode *getScopeNode(DebugLoc DL, const LLVMContext &Ctx) {
- if (MDNode *InlinedAt = DL.getInlinedAt(Ctx))
- return getScopeNode(DebugLoc::getFromDILocation(InlinedAt), Ctx);
- return DL.getScope(Ctx);
-}
-
-// Walk up the scope chain of given debug loc and find line number info
-// for the function.
-static DebugLoc getFnDebugLoc(DebugLoc DL, const LLVMContext &Ctx) {
- const MDNode *Scope = getScopeNode(DL, Ctx);
- DISubprogram SP = getDISubprogram(Scope);
- if (SP.isSubprogram()) {
- // Check for number of operands since the compatibility is
- // cheap here.
- if (SP->getNumOperands() > 19)
- return DebugLoc::get(SP.getScopeLineNumber(), 0, SP);
- else
- return DebugLoc::get(SP.getLineNumber(), 0, SP);
- }
-
- return DebugLoc();
-}
-
// Gather pre-function debug information. Assumes being called immediately
// after the function entry point has been emitted.
void DwarfDebug::beginFunction(const MachineFunction *MF) {
+ CurFn = MF;
// If there's no debug info for the function we're not going to do anything.
if (!MMI->hasDebugInfo())
@@ -1606,14 +1461,14 @@ void DwarfDebug::beginFunction(const MachineFunction *MF) {
// Make sure that each lexical scope will have a begin/end label.
identifyScopeMarkers();
- // Set DwarfCompileUnitID in MCContext to the Compile Unit this function
+ // Set DwarfDwarfCompileUnitID in MCContext to the Compile Unit this function
// belongs to so that we add to the correct per-cu line table in the
// non-asm case.
LexicalScope *FnScope = LScopes.getCurrentFunctionScope();
- CompileUnit *TheCU = SPMap.lookup(FnScope->getScopeNode());
+ DwarfCompileUnit *TheCU = SPMap.lookup(FnScope->getScopeNode());
assert(TheCU && "Unable to find compile unit!");
- if (Asm->TM.hasMCUseLoc() && Asm->OutStreamer.hasRawTextSupport())
- // Use a single line table if we are using .loc and generating assembly.
+ if (Asm->OutStreamer.hasRawTextSupport())
+ // Use a single line table if we are generating assembly.
Asm->OutStreamer.getContext().setDwarfCompileUnitID(0);
else
Asm->OutStreamer.getContext().setDwarfCompileUnitID(TheCU->getUniqueID());
@@ -1670,7 +1525,7 @@ void DwarfDebug::beginFunction(const MachineFunction *MF) {
// Terminate old register assignments that don't reach MI;
MachineFunction::const_iterator PrevMBB = Prev->getParent();
- if (PrevMBB != I && (!AtBlockEntry || llvm::next(PrevMBB) != I) &&
+ if (PrevMBB != I && (!AtBlockEntry || std::next(PrevMBB) != I) &&
isDbgValueInDefinedReg(Prev)) {
// Previous register assignment needs to terminate at the end of
// its basic block.
@@ -1681,7 +1536,7 @@ void DwarfDebug::beginFunction(const MachineFunction *MF) {
DEBUG(dbgs() << "Dropping DBG_VALUE for empty range:\n"
<< "\t" << *Prev << "\n");
History.pop_back();
- } else if (llvm::next(PrevMBB) != PrevMBB->getParent()->end())
+ } else if (std::next(PrevMBB) != PrevMBB->getParent()->end())
// Terminate after LastMI.
History.push_back(LastMI);
}
@@ -1690,7 +1545,7 @@ void DwarfDebug::beginFunction(const MachineFunction *MF) {
History.push_back(MI);
} else {
// Not a DBG_VALUE instruction.
- if (!MI->isLabel())
+ if (!MI->isPosition())
AtBlockEntry = false;
// First known non-DBG_VALUE and non-frame setup location marks
@@ -1700,12 +1555,10 @@ void DwarfDebug::beginFunction(const MachineFunction *MF) {
PrologEndLoc = MI->getDebugLoc();
// Check if the instruction clobbers any registers with debug vars.
- for (MachineInstr::const_mop_iterator MOI = MI->operands_begin(),
- MOE = MI->operands_end();
- MOI != MOE; ++MOI) {
- if (!MOI->isReg() || !MOI->isDef() || !MOI->getReg())
+ for (const MachineOperand &MO : MI->operands()) {
+ if (!MO.isReg() || !MO.isDef() || !MO.getReg())
continue;
- for (MCRegAliasIterator AI(MOI->getReg(), TRI, true); AI.isValid();
+ for (MCRegAliasIterator AI(MO.getReg(), TRI, true); AI.isValid();
++AI) {
unsigned Reg = *AI;
const MDNode *Var = LiveUserVar[Reg];
@@ -1738,9 +1591,8 @@ void DwarfDebug::beginFunction(const MachineFunction *MF) {
}
}
- for (DbgValueHistoryMap::iterator I = DbgValues.begin(), E = DbgValues.end();
- I != E; ++I) {
- SmallVectorImpl<const MachineInstr *> &History = I->second;
+ for (auto &I : DbgValues) {
+ SmallVectorImpl<const MachineInstr *> &History = I.second;
if (History.empty())
continue;
@@ -1759,8 +1611,7 @@ void DwarfDebug::beginFunction(const MachineFunction *MF) {
}
}
// Request labels for the full history.
- for (unsigned i = 0, e = History.size(); i != e; ++i) {
- const MachineInstr *MI = History[i];
+ for (const MachineInstr *MI : History) {
if (MI->isDebugValue())
requestLabelBeforeInsn(MI);
else
@@ -1774,7 +1625,7 @@ void DwarfDebug::beginFunction(const MachineFunction *MF) {
// Record beginning of function.
if (!PrologEndLoc.isUnknown()) {
DebugLoc FnStartDL =
- getFnDebugLoc(PrologEndLoc, MF->getFunction()->getContext());
+ PrologEndLoc.getFnDebugLoc(MF->getFunction()->getContext());
recordSourceLine(
FnStartDL.getLine(), FnStartDL.getCol(),
FnStartDL.getScope(MF->getFunction()->getContext()),
@@ -1817,27 +1668,42 @@ void DwarfDebug::addScopeVariable(LexicalScope *LS, DbgVariable *Var) {
// Gather and emit post-function debug information.
void DwarfDebug::endFunction(const MachineFunction *MF) {
- if (!MMI->hasDebugInfo() || LScopes.empty()) return;
+ // Every beginFunction(MF) call should be followed by an endFunction(MF) call,
+ // though the beginFunction may not be called at all.
+ // We should handle both cases.
+ if (CurFn == 0)
+ CurFn = MF;
+ else
+ assert(CurFn == MF);
+ assert(CurFn != 0);
+
+ if (!MMI->hasDebugInfo() || LScopes.empty()) {
+ // If we don't have a lexical scope for this function then there will
+ // be a hole in the range information. Keep note of this by setting the
+ // previously used section to nullptr.
+ PrevSection = nullptr;
+ PrevCU = nullptr;
+ CurFn = 0;
+ return;
+ }
// Define end label for subprogram.
- FunctionEndSym = Asm->GetTempSymbol("func_end",
- Asm->getFunctionNumber());
+ FunctionEndSym = Asm->GetTempSymbol("func_end", Asm->getFunctionNumber());
// Assumes in correct section after the entry point.
Asm->OutStreamer.EmitLabel(FunctionEndSym);
- // Set DwarfCompileUnitID in MCContext to default value.
+
+ // Set DwarfDwarfCompileUnitID in MCContext to default value.
Asm->OutStreamer.getContext().setDwarfCompileUnitID(0);
SmallPtrSet<const MDNode *, 16> ProcessedVars;
- collectVariableInfo(MF, ProcessedVars);
+ collectVariableInfo(ProcessedVars);
LexicalScope *FnScope = LScopes.getCurrentFunctionScope();
- CompileUnit *TheCU = SPMap.lookup(FnScope->getScopeNode());
+ DwarfCompileUnit *TheCU = SPMap.lookup(FnScope->getScopeNode());
assert(TheCU && "Unable to find compile unit!");
// Construct abstract scopes.
- ArrayRef<LexicalScope *> AList = LScopes.getAbstractScopesList();
- for (unsigned i = 0, e = AList.size(); i != e; ++i) {
- LexicalScope *AScope = AList[i];
+ for (LexicalScope *AScope : LScopes.getAbstractScopesList()) {
DISubprogram SP(AScope->getScopeNode());
if (SP.isSubprogram()) {
// Collect info for variables that were optimized out.
@@ -1861,14 +1727,18 @@ void DwarfDebug::endFunction(const MachineFunction *MF) {
}
DIE *CurFnDIE = constructScopeDIE(TheCU, FnScope);
-
- if (!MF->getTarget().Options.DisableFramePointerElim(*MF))
+ if (!CurFn->getTarget().Options.DisableFramePointerElim(*CurFn))
TheCU->addFlag(CurFnDIE, dwarf::DW_AT_APPLE_omit_frame_ptr);
+ // Add the range of this function to the list of ranges for the CU.
+ RangeSpan Span(FunctionBeginSym, FunctionEndSym);
+ TheCU->addRange(std::move(Span));
+ PrevSection = Asm->getCurrentSection();
+ PrevCU = TheCU;
+
// Clear debug info
- for (ScopeVariablesMap::iterator
- I = ScopeVariables.begin(), E = ScopeVariables.end(); I != E; ++I)
- DeleteContainerPointers(I->second);
+ for (auto &I : ScopeVariables)
+ DeleteContainerPointers(I.second);
ScopeVariables.clear();
DeleteContainerPointers(CurrentFnArguments);
UserVariables.clear();
@@ -1877,6 +1747,7 @@ void DwarfDebug::endFunction(const MachineFunction *MF) {
LabelsBeforeInsn.clear();
LabelsAfterInsn.clear();
PrevLabel = NULL;
+ CurFn = 0;
}
// Register a source line with debug info. Returns the unique label that was
@@ -1886,6 +1757,7 @@ void DwarfDebug::recordSourceLine(unsigned Line, unsigned Col, const MDNode *S,
StringRef Fn;
StringRef Dir;
unsigned Src = 1;
+ unsigned Discriminator = 0;
if (S) {
DIDescriptor Scope(S);
@@ -1909,13 +1781,16 @@ void DwarfDebug::recordSourceLine(unsigned Line, unsigned Col, const MDNode *S,
DILexicalBlock DB(S);
Fn = DB.getFilename();
Dir = DB.getDirectory();
+ Discriminator = DB.getDiscriminator();
} else
llvm_unreachable("Unexpected scope info");
- Src = getOrCreateSourceID(Fn, Dir,
- Asm->OutStreamer.getContext().getDwarfCompileUnitID());
+ unsigned CUID = Asm->OutStreamer.getContext().getDwarfCompileUnitID();
+ Src = static_cast<DwarfCompileUnit *>(InfoHolder.getUnits()[CUID])
+ ->getOrCreateSourceID(Fn, Dir);
}
- Asm->OutStreamer.EmitDwarfLocDirective(Src, Line, Col, Flags, 0, 0, Fn);
+ Asm->OutStreamer.EmitDwarfLocDirective(Src, Line, Col, Flags, 0,
+ Discriminator, Fn);
}
//===----------------------------------------------------------------------===//
@@ -1924,39 +1799,36 @@ void DwarfDebug::recordSourceLine(unsigned Line, unsigned Col, const MDNode *S,
// Compute the size and offset of a DIE. The offset is relative to start of the
// CU. It returns the offset after laying out the DIE.
-unsigned
-DwarfUnits::computeSizeAndOffset(DIE *Die, unsigned Offset) {
- // Get the children.
- const std::vector<DIE *> &Children = Die->getChildren();
-
+unsigned DwarfFile::computeSizeAndOffset(DIE *Die, unsigned Offset) {
// Record the abbreviation.
assignAbbrevNumber(Die->getAbbrev());
// Get the abbreviation for this DIE.
- unsigned AbbrevNumber = Die->getAbbrevNumber();
- const DIEAbbrev *Abbrev = Abbreviations[AbbrevNumber - 1];
+ const DIEAbbrev &Abbrev = Die->getAbbrev();
// Set DIE offset
Die->setOffset(Offset);
// Start the size with the size of abbreviation code.
- Offset += MCAsmInfo::getULEB128Size(AbbrevNumber);
+ Offset += getULEB128Size(Die->getAbbrevNumber());
- const SmallVectorImpl<DIEValue*> &Values = Die->getValues();
- const SmallVectorImpl<DIEAbbrevData> &AbbrevData = Abbrev->getData();
+ const SmallVectorImpl<DIEValue *> &Values = Die->getValues();
+ const SmallVectorImpl<DIEAbbrevData> &AbbrevData = Abbrev.getData();
// Size the DIE attribute values.
for (unsigned i = 0, N = Values.size(); i < N; ++i)
// Size attribute value.
Offset += Values[i]->SizeOf(Asm, AbbrevData[i].getForm());
+ // Get the children.
+ const std::vector<DIE *> &Children = Die->getChildren();
+
// Size the DIE children if any.
if (!Children.empty()) {
- assert(Abbrev->getChildrenFlag() == dwarf::DW_CHILDREN_yes &&
- "Children flag not set");
+ assert(Abbrev.hasChildren() && "Children flag not set");
- for (unsigned j = 0, M = Children.size(); j < M; ++j)
- Offset = computeSizeAndOffset(Children[j], Offset);
+ for (DIE *Child : Children)
+ Offset = computeSizeAndOffset(Child, Offset);
// End of children marker.
Offset += sizeof(int8_t);
@@ -1967,23 +1839,22 @@ DwarfUnits::computeSizeAndOffset(DIE *Die, unsigned Offset) {
}
// Compute the size and offset for each DIE.
-void DwarfUnits::computeSizeAndOffsets() {
+void DwarfFile::computeSizeAndOffsets() {
// Offset from the first CU in the debug info section is 0 initially.
unsigned SecOffset = 0;
// Iterate over each compile unit and set the size and offsets for each
// DIE within each compile unit. All offsets are CU relative.
- for (SmallVectorImpl<CompileUnit *>::iterator I = CUs.begin(),
- E = CUs.end(); I != E; ++I) {
- (*I)->setDebugInfoOffset(SecOffset);
+ for (DwarfUnit *TheU : CUs) {
+ TheU->setDebugInfoOffset(SecOffset);
// CU-relative offset is reset to 0 here.
- unsigned Offset = sizeof(int32_t) + // Length of Unit Info
- (*I)->getHeaderSize(); // Unit-specific headers
+ unsigned Offset = sizeof(int32_t) + // Length of Unit Info
+ TheU->getHeaderSize(); // Unit-specific headers
// EndOffset here is CU-relative, after laying out
// all of the CU DIE.
- unsigned EndOffset = computeSizeAndOffset((*I)->getCUDie(), Offset);
+ unsigned EndOffset = computeSizeAndOffset(TheU->getUnitDie(), Offset);
SecOffset += EndOffset;
}
}
@@ -1994,21 +1865,20 @@ void DwarfDebug::emitSectionLabels() {
// Dwarf sections base addresses.
DwarfInfoSectionSym =
- emitSectionSym(Asm, TLOF.getDwarfInfoSection(), "section_info");
+ emitSectionSym(Asm, TLOF.getDwarfInfoSection(), "section_info");
+ if (useSplitDwarf())
+ DwarfInfoDWOSectionSym =
+ emitSectionSym(Asm, TLOF.getDwarfInfoDWOSection(), "section_info_dwo");
DwarfAbbrevSectionSym =
- emitSectionSym(Asm, TLOF.getDwarfAbbrevSection(), "section_abbrev");
+ emitSectionSym(Asm, TLOF.getDwarfAbbrevSection(), "section_abbrev");
if (useSplitDwarf())
- DwarfAbbrevDWOSectionSym =
- emitSectionSym(Asm, TLOF.getDwarfAbbrevDWOSection(),
- "section_abbrev_dwo");
- emitSectionSym(Asm, TLOF.getDwarfARangesSection());
-
- if (const MCSection *MacroInfo = TLOF.getDwarfMacroInfoSection())
- emitSectionSym(Asm, MacroInfo);
+ DwarfAbbrevDWOSectionSym = emitSectionSym(
+ Asm, TLOF.getDwarfAbbrevDWOSection(), "section_abbrev_dwo");
+ if (GenerateARangeSection)
+ emitSectionSym(Asm, TLOF.getDwarfARangesSection());
DwarfLineSectionSym =
- emitSectionSym(Asm, TLOF.getDwarfLineSection(), "section_line");
- emitSectionSym(Asm, TLOF.getDwarfLocSection());
+ emitSectionSym(Asm, TLOF.getDwarfLineSection(), "section_line");
if (GenerateGnuPubSections) {
DwarfGnuPubNamesSectionSym =
emitSectionSym(Asm, TLOF.getDwarfGnuPubNamesSection());
@@ -2020,39 +1890,36 @@ void DwarfDebug::emitSectionLabels() {
}
DwarfStrSectionSym =
- emitSectionSym(Asm, TLOF.getDwarfStrSection(), "info_string");
+ emitSectionSym(Asm, TLOF.getDwarfStrSection(), "info_string");
if (useSplitDwarf()) {
DwarfStrDWOSectionSym =
- emitSectionSym(Asm, TLOF.getDwarfStrDWOSection(), "skel_string");
+ emitSectionSym(Asm, TLOF.getDwarfStrDWOSection(), "skel_string");
DwarfAddrSectionSym =
- emitSectionSym(Asm, TLOF.getDwarfAddrSection(), "addr_sec");
- }
- DwarfDebugRangeSectionSym = emitSectionSym(Asm, TLOF.getDwarfRangesSection(),
- "debug_range");
-
- DwarfDebugLocSectionSym = emitSectionSym(Asm, TLOF.getDwarfLocSection(),
- "section_debug_loc");
-
- TextSectionSym = emitSectionSym(Asm, TLOF.getTextSection(), "text_begin");
- emitSectionSym(Asm, TLOF.getDataSection());
+ emitSectionSym(Asm, TLOF.getDwarfAddrSection(), "addr_sec");
+ DwarfDebugLocSectionSym =
+ emitSectionSym(Asm, TLOF.getDwarfLocDWOSection(), "skel_loc");
+ } else
+ DwarfDebugLocSectionSym =
+ emitSectionSym(Asm, TLOF.getDwarfLocSection(), "section_debug_loc");
+ DwarfDebugRangeSectionSym =
+ emitSectionSym(Asm, TLOF.getDwarfRangesSection(), "debug_range");
}
// Recursively emits a debug information entry.
-void DwarfDebug::emitDIE(DIE *Die, ArrayRef<DIEAbbrev *> Abbrevs) {
+void DwarfDebug::emitDIE(DIE *Die) {
// Get the abbreviation for this DIE.
- unsigned AbbrevNumber = Die->getAbbrevNumber();
- const DIEAbbrev *Abbrev = Abbrevs[AbbrevNumber - 1];
+ const DIEAbbrev &Abbrev = Die->getAbbrev();
// Emit the code (index) for the abbreviation.
if (Asm->isVerbose())
- Asm->OutStreamer.AddComment("Abbrev [" + Twine(AbbrevNumber) + "] 0x" +
- Twine::utohexstr(Die->getOffset()) + ":0x" +
- Twine::utohexstr(Die->getSize()) + " " +
- dwarf::TagString(Abbrev->getTag()));
- Asm->EmitULEB128(AbbrevNumber);
+ Asm->OutStreamer.AddComment("Abbrev [" + Twine(Abbrev.getNumber()) +
+ "] 0x" + Twine::utohexstr(Die->getOffset()) +
+ ":0x" + Twine::utohexstr(Die->getSize()) + " " +
+ dwarf::TagString(Abbrev.getTag()));
+ Asm->EmitULEB128(Abbrev.getNumber());
- const SmallVectorImpl<DIEValue*> &Values = Die->getValues();
- const SmallVectorImpl<DIEAbbrevData> &AbbrevData = Abbrev->getData();
+ const SmallVectorImpl<DIEValue *> &Values = Die->getValues();
+ const SmallVectorImpl<DIEAbbrevData> &AbbrevData = Abbrev.getData();
// Emit the DIE attribute values.
for (unsigned i = 0, N = Values.size(); i < N; ++i) {
@@ -2060,159 +1927,73 @@ void DwarfDebug::emitDIE(DIE *Die, ArrayRef<DIEAbbrev *> Abbrevs) {
dwarf::Form Form = AbbrevData[i].getForm();
assert(Form && "Too many attributes for DIE (check abbreviation)");
- if (Asm->isVerbose())
+ if (Asm->isVerbose()) {
Asm->OutStreamer.AddComment(dwarf::AttributeString(Attr));
-
- switch (Attr) {
- case dwarf::DW_AT_abstract_origin:
- case dwarf::DW_AT_type:
- case dwarf::DW_AT_friend:
- case dwarf::DW_AT_specification:
- case dwarf::DW_AT_import:
- case dwarf::DW_AT_containing_type: {
- DIEEntry *E = cast<DIEEntry>(Values[i]);
- DIE *Origin = E->getEntry();
- unsigned Addr = Origin->getOffset();
- if (Form == dwarf::DW_FORM_ref_addr) {
- assert(!useSplitDwarf() && "TODO: dwo files can't have relocations.");
- // For DW_FORM_ref_addr, output the offset from beginning of debug info
- // section. Origin->getOffset() returns the offset from start of the
- // compile unit.
- CompileUnit *CU = CUDieMap.lookup(Origin->getCompileUnit());
- assert(CU && "CUDie should belong to a CU.");
- Addr += CU->getDebugInfoOffset();
- if (Asm->MAI->doesDwarfUseRelocationsAcrossSections())
- Asm->EmitLabelPlusOffset(DwarfInfoSectionSym, Addr,
- DIEEntry::getRefAddrSize(Asm));
- else
- Asm->EmitLabelOffsetDifference(DwarfInfoSectionSym, Addr,
- DwarfInfoSectionSym,
- DIEEntry::getRefAddrSize(Asm));
- } else {
- // Make sure Origin belong to the same CU.
- assert(Die->getCompileUnit() == Origin->getCompileUnit() &&
- "The referenced DIE should belong to the same CU in ref4");
- Asm->EmitInt32(Addr);
- }
- break;
- }
- case dwarf::DW_AT_ranges: {
- // DW_AT_range Value encodes offset in debug_range section.
- DIEInteger *V = cast<DIEInteger>(Values[i]);
-
- if (Asm->MAI->doesDwarfUseRelocationsAcrossSections()) {
- Asm->EmitLabelPlusOffset(DwarfDebugRangeSectionSym,
- V->getValue(),
- 4);
- } else {
- Asm->EmitLabelOffsetDifference(DwarfDebugRangeSectionSym,
- V->getValue(),
- DwarfDebugRangeSectionSym,
- 4);
- }
- break;
- }
- case dwarf::DW_AT_location: {
- if (DIELabel *L = dyn_cast<DIELabel>(Values[i])) {
- if (Asm->MAI->doesDwarfUseRelocationsAcrossSections())
- Asm->EmitSectionOffset(L->getValue(), DwarfDebugLocSectionSym);
- else
- Asm->EmitLabelDifference(L->getValue(), DwarfDebugLocSectionSym, 4);
- } else {
- Values[i]->EmitValue(Asm, Form);
- }
- break;
- }
- case dwarf::DW_AT_accessibility: {
- if (Asm->isVerbose()) {
- DIEInteger *V = cast<DIEInteger>(Values[i]);
- Asm->OutStreamer.AddComment(dwarf::AccessibilityString(V->getValue()));
- }
- Values[i]->EmitValue(Asm, Form);
- break;
- }
- default:
- // Emit an attribute using the defined form.
- Values[i]->EmitValue(Asm, Form);
- break;
+ if (Attr == dwarf::DW_AT_accessibility)
+ Asm->OutStreamer.AddComment(dwarf::AccessibilityString(
+ cast<DIEInteger>(Values[i])->getValue()));
}
+
+ // Emit an attribute using the defined form.
+ Values[i]->EmitValue(Asm, Form);
}
// Emit the DIE children if any.
- if (Abbrev->getChildrenFlag() == dwarf::DW_CHILDREN_yes) {
+ if (Abbrev.hasChildren()) {
const std::vector<DIE *> &Children = Die->getChildren();
- for (unsigned j = 0, M = Children.size(); j < M; ++j)
- emitDIE(Children[j], Abbrevs);
+ for (DIE *Child : Children)
+ emitDIE(Child);
- if (Asm->isVerbose())
- Asm->OutStreamer.AddComment("End Of Children Mark");
+ Asm->OutStreamer.AddComment("End Of Children Mark");
Asm->EmitInt8(0);
}
}
// Emit the various dwarf units to the unit section USection with
// the abbreviations going into ASection.
-void DwarfUnits::emitUnits(DwarfDebug *DD,
- const MCSection *USection,
- const MCSection *ASection,
- const MCSymbol *ASectionSym) {
- Asm->OutStreamer.SwitchSection(USection);
- for (SmallVectorImpl<CompileUnit *>::iterator I = CUs.begin(),
- E = CUs.end(); I != E; ++I) {
- CompileUnit *TheCU = *I;
- DIE *Die = TheCU->getCUDie();
+void DwarfFile::emitUnits(DwarfDebug *DD, const MCSymbol *ASectionSym) {
+ for (DwarfUnit *TheU : CUs) {
+ DIE *Die = TheU->getUnitDie();
+ const MCSection *USection = TheU->getSection();
+ Asm->OutStreamer.SwitchSection(USection);
// Emit the compile units header.
- Asm->OutStreamer
- .EmitLabel(Asm->GetTempSymbol(USection->getLabelBeginName(),
- TheCU->getUniqueID()));
+ Asm->OutStreamer.EmitLabel(TheU->getLabelBegin());
// Emit size of content not including length itself
Asm->OutStreamer.AddComment("Length of Unit");
- Asm->EmitInt32(TheCU->getHeaderSize() + Die->getSize());
+ Asm->EmitInt32(TheU->getHeaderSize() + Die->getSize());
- TheCU->emitHeader(ASection, ASectionSym);
+ TheU->emitHeader(ASectionSym);
- DD->emitDIE(Die, Abbreviations);
- Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol(USection->getLabelEndName(),
- TheCU->getUniqueID()));
+ DD->emitDIE(Die);
+ Asm->OutStreamer.EmitLabel(TheU->getLabelEnd());
}
}
// Emit the debug info section.
void DwarfDebug::emitDebugInfo() {
- DwarfUnits &Holder = useSplitDwarf() ? SkeletonHolder : InfoHolder;
+ DwarfFile &Holder = useSplitDwarf() ? SkeletonHolder : InfoHolder;
- Holder.emitUnits(this, Asm->getObjFileLowering().getDwarfInfoSection(),
- Asm->getObjFileLowering().getDwarfAbbrevSection(),
- DwarfAbbrevSectionSym);
+ Holder.emitUnits(this, DwarfAbbrevSectionSym);
}
// Emit the abbreviation section.
void DwarfDebug::emitAbbreviations() {
- if (!useSplitDwarf())
- emitAbbrevs(Asm->getObjFileLowering().getDwarfAbbrevSection(),
- &Abbreviations);
- else
- emitSkeletonAbbrevs(Asm->getObjFileLowering().getDwarfAbbrevSection());
+ DwarfFile &Holder = useSplitDwarf() ? SkeletonHolder : InfoHolder;
+
+ Holder.emitAbbrevs(Asm->getObjFileLowering().getDwarfAbbrevSection());
}
-void DwarfDebug::emitAbbrevs(const MCSection *Section,
- std::vector<DIEAbbrev *> *Abbrevs) {
+void DwarfFile::emitAbbrevs(const MCSection *Section) {
// Check to see if it is worth the effort.
- if (!Abbrevs->empty()) {
+ if (!Abbreviations.empty()) {
// Start the debug abbrev section.
Asm->OutStreamer.SwitchSection(Section);
- MCSymbol *Begin = Asm->GetTempSymbol(Section->getLabelBeginName());
- Asm->OutStreamer.EmitLabel(Begin);
-
// For each abbrevation.
- for (unsigned i = 0, N = Abbrevs->size(); i < N; ++i) {
- // Get abbreviation data
- const DIEAbbrev *Abbrev = Abbrevs->at(i);
-
+ for (const DIEAbbrev *Abbrev : Abbreviations) {
// Emit the abbrevations code (base 1 index.)
Asm->EmitULEB128(Abbrev->getNumber(), "Abbreviation Code");
@@ -2222,9 +2003,6 @@ void DwarfDebug::emitAbbrevs(const MCSection *Section,
// Mark end of abbreviations.
Asm->EmitULEB128(0, "EOM(3)");
-
- MCSymbol *End = Asm->GetTempSymbol(Section->getLabelEndName());
- Asm->OutStreamer.EmitLabel(End);
}
}
@@ -2241,8 +2019,9 @@ void DwarfDebug::emitEndOfLineMatrix(unsigned SectionEnd) {
Asm->OutStreamer.AddComment("Section end label");
- Asm->OutStreamer.EmitSymbolValue(Asm->GetTempSymbol("section_end",SectionEnd),
- Asm->getDataLayout().getPointerSize());
+ Asm->OutStreamer.EmitSymbolValue(
+ Asm->GetTempSymbol("section_end", SectionEnd),
+ Asm->getDataLayout().getPointerSize());
// Mark end of matrix.
Asm->OutStreamer.AddComment("DW_LNE_end_sequence");
@@ -2253,25 +2032,19 @@ void DwarfDebug::emitEndOfLineMatrix(unsigned SectionEnd) {
// Emit visible names into a hashed accelerator table section.
void DwarfDebug::emitAccelNames() {
- DwarfAccelTable AT(DwarfAccelTable::Atom(dwarf::DW_ATOM_die_offset,
- dwarf::DW_FORM_data4));
- for (DenseMap<const MDNode *, CompileUnit *>::iterator I = CUMap.begin(),
- E = CUMap.end(); I != E; ++I) {
- CompileUnit *TheCU = I->second;
- const StringMap<std::vector<DIE*> > &Names = TheCU->getAccelNames();
- for (StringMap<std::vector<DIE*> >::const_iterator
- GI = Names.begin(), GE = Names.end(); GI != GE; ++GI) {
- StringRef Name = GI->getKey();
- const std::vector<DIE *> &Entities = GI->second;
- for (std::vector<DIE *>::const_iterator DI = Entities.begin(),
- DE = Entities.end(); DI != DE; ++DI)
- AT.AddName(Name, (*DI));
+ DwarfAccelTable AT(
+ DwarfAccelTable::Atom(dwarf::DW_ATOM_die_offset, dwarf::DW_FORM_data4));
+ for (DwarfUnit *TheU : getUnits()) {
+ for (const auto &GI : TheU->getAccelNames()) {
+ StringRef Name = GI.getKey();
+ for (const DIE *D : GI.second)
+ AT.AddName(Name, D);
}
}
AT.FinalizeTable(Asm, "Names");
Asm->OutStreamer.SwitchSection(
- Asm->getObjFileLowering().getDwarfAccelNamesSection());
+ Asm->getObjFileLowering().getDwarfAccelNamesSection());
MCSymbol *SectionBegin = Asm->GetTempSymbol("names_begin");
Asm->OutStreamer.EmitLabel(SectionBegin);
@@ -2282,25 +2055,19 @@ void DwarfDebug::emitAccelNames() {
// Emit objective C classes and categories into a hashed accelerator table
// section.
void DwarfDebug::emitAccelObjC() {
- DwarfAccelTable AT(DwarfAccelTable::Atom(dwarf::DW_ATOM_die_offset,
- dwarf::DW_FORM_data4));
- for (DenseMap<const MDNode *, CompileUnit *>::iterator I = CUMap.begin(),
- E = CUMap.end(); I != E; ++I) {
- CompileUnit *TheCU = I->second;
- const StringMap<std::vector<DIE*> > &Names = TheCU->getAccelObjC();
- for (StringMap<std::vector<DIE*> >::const_iterator
- GI = Names.begin(), GE = Names.end(); GI != GE; ++GI) {
- StringRef Name = GI->getKey();
- const std::vector<DIE *> &Entities = GI->second;
- for (std::vector<DIE *>::const_iterator DI = Entities.begin(),
- DE = Entities.end(); DI != DE; ++DI)
- AT.AddName(Name, (*DI));
+ DwarfAccelTable AT(
+ DwarfAccelTable::Atom(dwarf::DW_ATOM_die_offset, dwarf::DW_FORM_data4));
+ for (DwarfUnit *TheU : getUnits()) {
+ for (const auto &GI : TheU->getAccelObjC()) {
+ StringRef Name = GI.getKey();
+ for (const DIE *D : GI.second)
+ AT.AddName(Name, D);
}
}
AT.FinalizeTable(Asm, "ObjC");
- Asm->OutStreamer.SwitchSection(Asm->getObjFileLowering()
- .getDwarfAccelObjCSection());
+ Asm->OutStreamer.SwitchSection(
+ Asm->getObjFileLowering().getDwarfAccelObjCSection());
MCSymbol *SectionBegin = Asm->GetTempSymbol("objc_begin");
Asm->OutStreamer.EmitLabel(SectionBegin);
@@ -2310,25 +2077,19 @@ void DwarfDebug::emitAccelObjC() {
// Emit namespace dies into a hashed accelerator table.
void DwarfDebug::emitAccelNamespaces() {
- DwarfAccelTable AT(DwarfAccelTable::Atom(dwarf::DW_ATOM_die_offset,
- dwarf::DW_FORM_data4));
- for (DenseMap<const MDNode *, CompileUnit *>::iterator I = CUMap.begin(),
- E = CUMap.end(); I != E; ++I) {
- CompileUnit *TheCU = I->second;
- const StringMap<std::vector<DIE*> > &Names = TheCU->getAccelNamespace();
- for (StringMap<std::vector<DIE*> >::const_iterator
- GI = Names.begin(), GE = Names.end(); GI != GE; ++GI) {
- StringRef Name = GI->getKey();
- const std::vector<DIE *> &Entities = GI->second;
- for (std::vector<DIE *>::const_iterator DI = Entities.begin(),
- DE = Entities.end(); DI != DE; ++DI)
- AT.AddName(Name, (*DI));
+ DwarfAccelTable AT(
+ DwarfAccelTable::Atom(dwarf::DW_ATOM_die_offset, dwarf::DW_FORM_data4));
+ for (DwarfUnit *TheU : getUnits()) {
+ for (const auto &GI : TheU->getAccelNamespace()) {
+ StringRef Name = GI.getKey();
+ for (const DIE *D : GI.second)
+ AT.AddName(Name, D);
}
}
AT.FinalizeTable(Asm, "namespac");
- Asm->OutStreamer.SwitchSection(Asm->getObjFileLowering()
- .getDwarfAccelNamespaceSection());
+ Asm->OutStreamer.SwitchSection(
+ Asm->getObjFileLowering().getDwarfAccelNamespaceSection());
MCSymbol *SectionBegin = Asm->GetTempSymbol("namespac_begin");
Asm->OutStreamer.EmitLabel(SectionBegin);
@@ -2339,31 +2100,24 @@ void DwarfDebug::emitAccelNamespaces() {
// Emit type dies into a hashed accelerator table.
void DwarfDebug::emitAccelTypes() {
std::vector<DwarfAccelTable::Atom> Atoms;
- Atoms.push_back(DwarfAccelTable::Atom(dwarf::DW_ATOM_die_offset,
- dwarf::DW_FORM_data4));
- Atoms.push_back(DwarfAccelTable::Atom(dwarf::DW_ATOM_die_tag,
- dwarf::DW_FORM_data2));
- Atoms.push_back(DwarfAccelTable::Atom(dwarf::DW_ATOM_type_flags,
- dwarf::DW_FORM_data1));
+ Atoms.push_back(
+ DwarfAccelTable::Atom(dwarf::DW_ATOM_die_offset, dwarf::DW_FORM_data4));
+ Atoms.push_back(
+ DwarfAccelTable::Atom(dwarf::DW_ATOM_die_tag, dwarf::DW_FORM_data2));
+ Atoms.push_back(
+ DwarfAccelTable::Atom(dwarf::DW_ATOM_type_flags, dwarf::DW_FORM_data1));
DwarfAccelTable AT(Atoms);
- for (DenseMap<const MDNode *, CompileUnit *>::iterator I = CUMap.begin(),
- E = CUMap.end(); I != E; ++I) {
- CompileUnit *TheCU = I->second;
- const StringMap<std::vector<std::pair<DIE*, unsigned > > > &Names
- = TheCU->getAccelTypes();
- for (StringMap<std::vector<std::pair<DIE*, unsigned> > >::const_iterator
- GI = Names.begin(), GE = Names.end(); GI != GE; ++GI) {
- StringRef Name = GI->getKey();
- const std::vector<std::pair<DIE *, unsigned> > &Entities = GI->second;
- for (std::vector<std::pair<DIE *, unsigned> >::const_iterator DI
- = Entities.begin(), DE = Entities.end(); DI !=DE; ++DI)
- AT.AddName(Name, (*DI).first, (*DI).second);
+ for (DwarfUnit *TheU : getUnits()) {
+ for (const auto &GI : TheU->getAccelTypes()) {
+ StringRef Name = GI.getKey();
+ for (const auto &DI : GI.second)
+ AT.AddName(Name, DI.first, DI.second);
}
}
AT.FinalizeTable(Asm, "types");
- Asm->OutStreamer.SwitchSection(Asm->getObjFileLowering()
- .getDwarfAccelTypesSection());
+ Asm->OutStreamer.SwitchSection(
+ Asm->getObjFileLowering().getDwarfAccelTypesSection());
MCSymbol *SectionBegin = Asm->GetTempSymbol("types_begin");
Asm->OutStreamer.EmitLabel(SectionBegin);
@@ -2386,8 +2140,8 @@ void DwarfDebug::emitAccelTypes() {
// reference in the pubname header doesn't change.
/// computeIndexValue - Compute the gdb index value for the DIE and CU.
-static dwarf::PubIndexEntryDescriptor computeIndexValue(CompileUnit *CU,
- DIE *Die) {
+static dwarf::PubIndexEntryDescriptor computeIndexValue(DwarfUnit *CU,
+ const DIE *Die) {
dwarf::GDBIndexEntryLinkage Linkage = dwarf::GIEL_STATIC;
// We could have a specification DIE that has our most of our knowledge,
@@ -2431,176 +2185,109 @@ static dwarf::PubIndexEntryDescriptor computeIndexValue(CompileUnit *CU,
/// emitDebugPubNames - Emit visible names into a debug pubnames section.
///
void DwarfDebug::emitDebugPubNames(bool GnuStyle) {
- const MCSection *ISec = Asm->getObjFileLowering().getDwarfInfoSection();
const MCSection *PSec =
GnuStyle ? Asm->getObjFileLowering().getDwarfGnuPubNamesSection()
: Asm->getObjFileLowering().getDwarfPubNamesSection();
- typedef DenseMap<const MDNode*, CompileUnit*> CUMapType;
- for (CUMapType::iterator I = CUMap.begin(), E = CUMap.end(); I != E; ++I) {
- CompileUnit *TheCU = I->second;
- unsigned ID = TheCU->getUniqueID();
+ emitDebugPubSection(GnuStyle, PSec, "Names", &DwarfUnit::getGlobalNames);
+}
+
+void DwarfDebug::emitDebugPubSection(
+ bool GnuStyle, const MCSection *PSec, StringRef Name,
+ const StringMap<const DIE *> &(DwarfUnit::*Accessor)() const) {
+ for (const auto &NU : CUMap) {
+ DwarfCompileUnit *TheU = NU.second;
+
+ const auto &Globals = (TheU->*Accessor)();
+
+ if (Globals.empty())
+ continue;
+
+ if (auto Skeleton = static_cast<DwarfCompileUnit *>(TheU->getSkeleton()))
+ TheU = Skeleton;
+ unsigned ID = TheU->getUniqueID();
// Start the dwarf pubnames section.
Asm->OutStreamer.SwitchSection(PSec);
- // Emit a label so we can reference the beginning of this pubname section.
- if (GnuStyle)
- Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("gnu_pubnames",
- TheCU->getUniqueID()));
-
// Emit the header.
- Asm->OutStreamer.AddComment("Length of Public Names Info");
- Asm->EmitLabelDifference(Asm->GetTempSymbol("pubnames_end", ID),
- Asm->GetTempSymbol("pubnames_begin", ID), 4);
+ Asm->OutStreamer.AddComment("Length of Public " + Name + " Info");
+ MCSymbol *BeginLabel = Asm->GetTempSymbol("pub" + Name + "_begin", ID);
+ MCSymbol *EndLabel = Asm->GetTempSymbol("pub" + Name + "_end", ID);
+ Asm->EmitLabelDifference(EndLabel, BeginLabel, 4);
- Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("pubnames_begin", ID));
+ Asm->OutStreamer.EmitLabel(BeginLabel);
Asm->OutStreamer.AddComment("DWARF Version");
Asm->EmitInt16(dwarf::DW_PUBNAMES_VERSION);
Asm->OutStreamer.AddComment("Offset of Compilation Unit Info");
- Asm->EmitSectionOffset(Asm->GetTempSymbol(ISec->getLabelBeginName(), ID),
- DwarfInfoSectionSym);
+ Asm->EmitSectionOffset(TheU->getLabelBegin(), TheU->getSectionSym());
Asm->OutStreamer.AddComment("Compilation Unit Length");
- Asm->EmitLabelDifference(Asm->GetTempSymbol(ISec->getLabelEndName(), ID),
- Asm->GetTempSymbol(ISec->getLabelBeginName(), ID),
- 4);
+ Asm->EmitLabelDifference(TheU->getLabelEnd(), TheU->getLabelBegin(), 4);
// Emit the pubnames for this compilation unit.
- const StringMap<DIE*> &Globals = TheCU->getGlobalNames();
- for (StringMap<DIE*>::const_iterator
- GI = Globals.begin(), GE = Globals.end(); GI != GE; ++GI) {
- const char *Name = GI->getKeyData();
- DIE *Entity = GI->second;
+ for (const auto &GI : Globals) {
+ const char *Name = GI.getKeyData();
+ const DIE *Entity = GI.second;
Asm->OutStreamer.AddComment("DIE offset");
Asm->EmitInt32(Entity->getOffset());
if (GnuStyle) {
- dwarf::PubIndexEntryDescriptor Desc = computeIndexValue(TheCU, Entity);
+ dwarf::PubIndexEntryDescriptor Desc = computeIndexValue(TheU, Entity);
Asm->OutStreamer.AddComment(
Twine("Kind: ") + dwarf::GDBIndexEntryKindString(Desc.Kind) + ", " +
dwarf::GDBIndexEntryLinkageString(Desc.Linkage));
Asm->EmitInt8(Desc.toBits());
}
- if (Asm->isVerbose())
- Asm->OutStreamer.AddComment("External Name");
- Asm->OutStreamer.EmitBytes(StringRef(Name, GI->getKeyLength()+1));
+ Asm->OutStreamer.AddComment("External Name");
+ Asm->OutStreamer.EmitBytes(StringRef(Name, GI.getKeyLength() + 1));
}
Asm->OutStreamer.AddComment("End Mark");
Asm->EmitInt32(0);
- Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("pubnames_end", ID));
+ Asm->OutStreamer.EmitLabel(EndLabel);
}
}
void DwarfDebug::emitDebugPubTypes(bool GnuStyle) {
- const MCSection *ISec = Asm->getObjFileLowering().getDwarfInfoSection();
const MCSection *PSec =
GnuStyle ? Asm->getObjFileLowering().getDwarfGnuPubTypesSection()
: Asm->getObjFileLowering().getDwarfPubTypesSection();
- for (DenseMap<const MDNode *, CompileUnit *>::iterator I = CUMap.begin(),
- E = CUMap.end();
- I != E; ++I) {
- CompileUnit *TheCU = I->second;
- // Start the dwarf pubtypes section.
- Asm->OutStreamer.SwitchSection(PSec);
-
- // Emit a label so we can reference the beginning of this pubtype section.
- if (GnuStyle)
- Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("gnu_pubtypes",
- TheCU->getUniqueID()));
-
- // Emit the header.
- Asm->OutStreamer.AddComment("Length of Public Types Info");
- Asm->EmitLabelDifference(
- Asm->GetTempSymbol("pubtypes_end", TheCU->getUniqueID()),
- Asm->GetTempSymbol("pubtypes_begin", TheCU->getUniqueID()), 4);
-
- Asm->OutStreamer.EmitLabel(
- Asm->GetTempSymbol("pubtypes_begin", TheCU->getUniqueID()));
-
- if (Asm->isVerbose())
- Asm->OutStreamer.AddComment("DWARF Version");
- Asm->EmitInt16(dwarf::DW_PUBTYPES_VERSION);
-
- Asm->OutStreamer.AddComment("Offset of Compilation Unit Info");
- Asm->EmitSectionOffset(
- Asm->GetTempSymbol(ISec->getLabelBeginName(), TheCU->getUniqueID()),
- DwarfInfoSectionSym);
-
- Asm->OutStreamer.AddComment("Compilation Unit Length");
- Asm->EmitLabelDifference(
- Asm->GetTempSymbol(ISec->getLabelEndName(), TheCU->getUniqueID()),
- Asm->GetTempSymbol(ISec->getLabelBeginName(), TheCU->getUniqueID()), 4);
-
- // Emit the pubtypes.
- const StringMap<DIE *> &Globals = TheCU->getGlobalTypes();
- for (StringMap<DIE *>::const_iterator GI = Globals.begin(),
- GE = Globals.end();
- GI != GE; ++GI) {
- const char *Name = GI->getKeyData();
- DIE *Entity = GI->second;
-
- if (Asm->isVerbose())
- Asm->OutStreamer.AddComment("DIE offset");
- Asm->EmitInt32(Entity->getOffset());
-
- if (GnuStyle) {
- dwarf::PubIndexEntryDescriptor Desc = computeIndexValue(TheCU, Entity);
- Asm->OutStreamer.AddComment(
- Twine("Kind: ") + dwarf::GDBIndexEntryKindString(Desc.Kind) + ", " +
- dwarf::GDBIndexEntryLinkageString(Desc.Linkage));
- Asm->EmitInt8(Desc.toBits());
- }
-
- if (Asm->isVerbose())
- Asm->OutStreamer.AddComment("External Name");
-
- // Emit the name with a terminating null byte.
- Asm->OutStreamer.EmitBytes(StringRef(Name, GI->getKeyLength() + 1));
- }
-
- Asm->OutStreamer.AddComment("End Mark");
- Asm->EmitInt32(0);
- Asm->OutStreamer.EmitLabel(
- Asm->GetTempSymbol("pubtypes_end", TheCU->getUniqueID()));
- }
+ emitDebugPubSection(GnuStyle, PSec, "Types", &DwarfUnit::getGlobalTypes);
}
// Emit strings into a string section.
-void DwarfUnits::emitStrings(const MCSection *StrSection,
- const MCSection *OffsetSection = NULL,
- const MCSymbol *StrSecSym = NULL) {
+void DwarfFile::emitStrings(const MCSection *StrSection,
+ const MCSection *OffsetSection = NULL,
+ const MCSymbol *StrSecSym = NULL) {
- if (StringPool.empty()) return;
+ if (StringPool.empty())
+ return;
// 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<std::pair<unsigned,
- StringMapEntry<std::pair<MCSymbol*, unsigned> >*>, 64> Entries;
+ SmallVector<std::pair<unsigned, const StrPool::value_type *>, 64 > Entries;
- for (StringMap<std::pair<MCSymbol*, unsigned> >::iterator
- I = StringPool.begin(), E = StringPool.end();
- I != E; ++I)
- Entries.push_back(std::make_pair(I->second.second, &*I));
+ for (const auto &I : StringPool)
+ Entries.push_back(std::make_pair(I.second.second, &I));
array_pod_sort(Entries.begin(), Entries.end());
- for (unsigned i = 0, e = Entries.size(); i != e; ++i) {
+ for (const auto &Entry : Entries) {
// Emit a label for reference from debug information entries.
- Asm->OutStreamer.EmitLabel(Entries[i].second->getValue().first);
+ Asm->OutStreamer.EmitLabel(Entry.second->getValue().first);
// Emit the string itself with a terminating null byte.
- Asm->OutStreamer.EmitBytes(StringRef(Entries[i].second->getKeyData(),
- Entries[i].second->getKeyLength()+1));
+ Asm->OutStreamer.EmitBytes(StringRef(Entry.second->getKeyData(),
+ Entry.second->getKeyLength() + 1));
}
// If we've got an offset section go ahead and emit that now as well.
@@ -2608,17 +2295,18 @@ void DwarfUnits::emitStrings(const MCSection *StrSection,
Asm->OutStreamer.SwitchSection(OffsetSection);
unsigned offset = 0;
unsigned size = 4; // FIXME: DWARF64 is 8.
- for (unsigned i = 0, e = Entries.size(); i != e; ++i) {
+ for (const auto &Entry : Entries) {
Asm->OutStreamer.EmitIntValue(offset, size);
- offset += Entries[i].second->getKeyLength() + 1;
+ offset += Entry.second->getKeyLength() + 1;
}
}
}
-// Emit strings into a string section.
-void DwarfUnits::emitAddresses(const MCSection *AddrSection) {
+// Emit addresses into the section given.
+void DwarfFile::emitAddresses(const MCSection *AddrSection) {
- if (AddressPool.empty()) return;
+ if (AddressPool.empty())
+ return;
// Start the dwarf addr section.
Asm->OutStreamer.SwitchSection(AddrSection);
@@ -2626,147 +2314,143 @@ void DwarfUnits::emitAddresses(const MCSection *AddrSection) {
// Order the address pool entries by ID
SmallVector<const MCExpr *, 64> Entries(AddressPool.size());
- for (DenseMap<const MCExpr *, unsigned>::iterator I = AddressPool.begin(),
- E = AddressPool.end();
- I != E; ++I)
- Entries[I->second] = I->first;
-
- for (unsigned i = 0, e = Entries.size(); i != e; ++i) {
- // Emit an expression for reference from debug information entries.
- if (const MCExpr *Expr = Entries[i])
- Asm->OutStreamer.EmitValue(Expr, Asm->getDataLayout().getPointerSize());
- else
- Asm->OutStreamer.EmitIntValue(0, Asm->getDataLayout().getPointerSize());
- }
+ for (const auto &I : AddressPool)
+ Entries[I.second.Number] =
+ I.second.TLS
+ ? Asm->getObjFileLowering().getDebugThreadLocalSymbol(I.first)
+ : MCSymbolRefExpr::Create(I.first, Asm->OutContext);
+ for (const MCExpr *Entry : Entries)
+ Asm->OutStreamer.EmitValue(Entry, Asm->getDataLayout().getPointerSize());
}
// Emit visible names into a debug str section.
void DwarfDebug::emitDebugStr() {
- DwarfUnits &Holder = useSplitDwarf() ? SkeletonHolder : InfoHolder;
+ DwarfFile &Holder = useSplitDwarf() ? SkeletonHolder : InfoHolder;
Holder.emitStrings(Asm->getObjFileLowering().getDwarfStrSection());
}
-// Emit locations into the debug loc section.
-void DwarfDebug::emitDebugLoc() {
- if (DotDebugLocEntries.empty())
- return;
-
- for (SmallVectorImpl<DotDebugLocEntry>::iterator
- I = DotDebugLocEntries.begin(), E = DotDebugLocEntries.end();
- I != E; ++I) {
- DotDebugLocEntry &Entry = *I;
- if (I + 1 != DotDebugLocEntries.end())
- Entry.Merge(I+1);
- }
-
- // Start the dwarf loc section.
- Asm->OutStreamer.SwitchSection(
- Asm->getObjFileLowering().getDwarfLocSection());
- unsigned char Size = Asm->getDataLayout().getPointerSize();
- Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("debug_loc", 0));
- unsigned index = 1;
- for (SmallVectorImpl<DotDebugLocEntry>::iterator
- I = DotDebugLocEntries.begin(), E = DotDebugLocEntries.end();
- I != E; ++I, ++index) {
- DotDebugLocEntry &Entry = *I;
- if (Entry.isMerged()) continue;
- if (Entry.isEmpty()) {
- Asm->OutStreamer.EmitIntValue(0, Size);
- Asm->OutStreamer.EmitIntValue(0, Size);
- Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("debug_loc", index));
+void DwarfDebug::emitDebugLocEntry(ByteStreamer &Streamer,
+ const DebugLocEntry &Entry) {
+ DIVariable DV(Entry.getVariable());
+ if (Entry.isInt()) {
+ DIBasicType BTy(resolve(DV.getType()));
+ if (BTy.Verify() && (BTy.getEncoding() == dwarf::DW_ATE_signed ||
+ BTy.getEncoding() == dwarf::DW_ATE_signed_char)) {
+ Streamer.EmitInt8(dwarf::DW_OP_consts, "DW_OP_consts");
+ Streamer.EmitSLEB128(Entry.getInt());
} else {
- Asm->OutStreamer.EmitSymbolValue(Entry.getBeginSym(), Size);
- Asm->OutStreamer.EmitSymbolValue(Entry.getEndSym(), Size);
- DIVariable DV(Entry.getVariable());
- Asm->OutStreamer.AddComment("Loc expr size");
- MCSymbol *begin = Asm->OutStreamer.getContext().CreateTempSymbol();
- MCSymbol *end = Asm->OutStreamer.getContext().CreateTempSymbol();
- Asm->EmitLabelDifference(end, begin, 2);
- Asm->OutStreamer.EmitLabel(begin);
- if (Entry.isInt()) {
- DIBasicType BTy(DV.getType());
- if (BTy.Verify() &&
- (BTy.getEncoding() == dwarf::DW_ATE_signed
- || BTy.getEncoding() == dwarf::DW_ATE_signed_char)) {
- Asm->OutStreamer.AddComment("DW_OP_consts");
- Asm->EmitInt8(dwarf::DW_OP_consts);
- Asm->EmitSLEB128(Entry.getInt());
+ Streamer.EmitInt8(dwarf::DW_OP_constu, "DW_OP_constu");
+ Streamer.EmitULEB128(Entry.getInt());
+ }
+ } else if (Entry.isLocation()) {
+ MachineLocation Loc = Entry.getLoc();
+ if (!DV.hasComplexAddress())
+ // Regular entry.
+ Asm->EmitDwarfRegOp(Streamer, Loc, DV.isIndirect());
+ else {
+ // Complex address entry.
+ unsigned N = DV.getNumAddrElements();
+ unsigned i = 0;
+ if (N >= 2 && DV.getAddrElement(0) == DIBuilder::OpPlus) {
+ if (Loc.getOffset()) {
+ i = 2;
+ Asm->EmitDwarfRegOp(Streamer, Loc, DV.isIndirect());
+ Streamer.EmitInt8(dwarf::DW_OP_deref, "DW_OP_deref");
+ Streamer.EmitInt8(dwarf::DW_OP_plus_uconst, "DW_OP_plus_uconst");
+ Streamer.EmitSLEB128(DV.getAddrElement(1));
} else {
- Asm->OutStreamer.AddComment("DW_OP_constu");
- Asm->EmitInt8(dwarf::DW_OP_constu);
- Asm->EmitULEB128(Entry.getInt());
+ // If first address element is OpPlus then emit
+ // DW_OP_breg + Offset instead of DW_OP_reg + Offset.
+ MachineLocation TLoc(Loc.getReg(), DV.getAddrElement(1));
+ Asm->EmitDwarfRegOp(Streamer, TLoc, DV.isIndirect());
+ i = 2;
}
- } else if (Entry.isLocation()) {
- MachineLocation Loc = Entry.getLoc();
- if (!DV.hasComplexAddress())
- // Regular entry.
- Asm->EmitDwarfRegOp(Loc, DV.isIndirect());
- else {
- // Complex address entry.
- unsigned N = DV.getNumAddrElements();
- unsigned i = 0;
- if (N >= 2 && DV.getAddrElement(0) == DIBuilder::OpPlus) {
- if (Loc.getOffset()) {
- i = 2;
- Asm->EmitDwarfRegOp(Loc, DV.isIndirect());
- Asm->OutStreamer.AddComment("DW_OP_deref");
- Asm->EmitInt8(dwarf::DW_OP_deref);
- Asm->OutStreamer.AddComment("DW_OP_plus_uconst");
- Asm->EmitInt8(dwarf::DW_OP_plus_uconst);
- Asm->EmitSLEB128(DV.getAddrElement(1));
- } else {
- // If first address element is OpPlus then emit
- // DW_OP_breg + Offset instead of DW_OP_reg + Offset.
- MachineLocation TLoc(Loc.getReg(), DV.getAddrElement(1));
- Asm->EmitDwarfRegOp(TLoc, DV.isIndirect());
- i = 2;
- }
- } else {
- Asm->EmitDwarfRegOp(Loc, DV.isIndirect());
- }
+ } else {
+ Asm->EmitDwarfRegOp(Streamer, Loc, DV.isIndirect());
+ }
- // Emit remaining complex address elements.
- for (; i < N; ++i) {
- uint64_t Element = DV.getAddrElement(i);
- if (Element == DIBuilder::OpPlus) {
- Asm->EmitInt8(dwarf::DW_OP_plus_uconst);
- Asm->EmitULEB128(DV.getAddrElement(++i));
- } else if (Element == DIBuilder::OpDeref) {
- if (!Loc.isReg())
- Asm->EmitInt8(dwarf::DW_OP_deref);
- } else
- llvm_unreachable("unknown Opcode found in complex address");
- }
- }
+ // Emit remaining complex address elements.
+ for (; i < N; ++i) {
+ uint64_t Element = DV.getAddrElement(i);
+ if (Element == DIBuilder::OpPlus) {
+ Streamer.EmitInt8(dwarf::DW_OP_plus_uconst, "DW_OP_plus_uconst");
+ Streamer.EmitULEB128(DV.getAddrElement(++i));
+ } else if (Element == DIBuilder::OpDeref) {
+ if (!Loc.isReg())
+ Streamer.EmitInt8(dwarf::DW_OP_deref, "DW_OP_deref");
+ } else
+ llvm_unreachable("unknown Opcode found in complex address");
}
- // else ... ignore constant fp. There is not any good way to
- // to represent them here in dwarf.
- Asm->OutStreamer.EmitLabel(end);
}
}
+ // else ... ignore constant fp. There is not any good way to
+ // to represent them here in dwarf.
+ // FIXME: ^
}
-struct SymbolCUSorter {
- SymbolCUSorter(const MCStreamer &s) : Streamer(s) {}
- const MCStreamer &Streamer;
+void DwarfDebug::emitDebugLocEntryLocation(const DebugLocEntry &Entry) {
+ Asm->OutStreamer.AddComment("Loc expr size");
+ MCSymbol *begin = Asm->OutStreamer.getContext().CreateTempSymbol();
+ MCSymbol *end = Asm->OutStreamer.getContext().CreateTempSymbol();
+ Asm->EmitLabelDifference(end, begin, 2);
+ Asm->OutStreamer.EmitLabel(begin);
+ // Emit the entry.
+ APByteStreamer Streamer(*Asm);
+ emitDebugLocEntry(Streamer, Entry);
+ // Close the range.
+ Asm->OutStreamer.EmitLabel(end);
+}
- bool operator() (const SymbolCU &A, const SymbolCU &B) {
- unsigned IA = A.Sym ? Streamer.GetSymbolOrder(A.Sym) : 0;
- unsigned IB = B.Sym ? Streamer.GetSymbolOrder(B.Sym) : 0;
+// Emit locations into the debug loc section.
+void DwarfDebug::emitDebugLoc() {
+ // Start the dwarf loc section.
+ Asm->OutStreamer.SwitchSection(
+ Asm->getObjFileLowering().getDwarfLocSection());
+ unsigned char Size = Asm->getDataLayout().getPointerSize();
+ for (const auto &DebugLoc : DotDebugLocEntries) {
+ Asm->OutStreamer.EmitLabel(DebugLoc.Label);
+ for (const auto &Entry : DebugLoc.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.
+ const DwarfCompileUnit *CU = Entry.getCU();
+ if (CU->getRanges().size() == 1) {
+ // Grab the begin symbol from the first range as our base.
+ const MCSymbol *Base = CU->getRanges()[0].getStart();
+ Asm->EmitLabelDifference(Entry.getBeginSym(), Base, Size);
+ Asm->EmitLabelDifference(Entry.getEndSym(), Base, Size);
+ } else {
+ Asm->OutStreamer.EmitSymbolValue(Entry.getBeginSym(), Size);
+ Asm->OutStreamer.EmitSymbolValue(Entry.getEndSym(), Size);
+ }
- // Symbols with no order assigned should be placed at the end.
- // (e.g. section end labels)
- if (IA == 0)
- IA = (unsigned)(-1);
- if (IB == 0)
- IB = (unsigned)(-1);
- return IA < IB;
+ emitDebugLocEntryLocation(Entry);
+ }
+ Asm->OutStreamer.EmitIntValue(0, Size);
+ Asm->OutStreamer.EmitIntValue(0, Size);
}
-};
+}
-static bool CUSort(const CompileUnit *A, const CompileUnit *B) {
- return (A->getUniqueID() < B->getUniqueID());
+void DwarfDebug::emitDebugLocDWO() {
+ Asm->OutStreamer.SwitchSection(
+ Asm->getObjFileLowering().getDwarfLocDWOSection());
+ for (const auto &DebugLoc : DotDebugLocEntries) {
+ Asm->OutStreamer.EmitLabel(DebugLoc.Label);
+ for (const auto &Entry : DebugLoc.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?)
+ Asm->EmitInt8(dwarf::DW_LLE_start_length_entry);
+ unsigned idx = InfoHolder.getAddrPoolIndex(Entry.getBeginSym());
+ Asm->EmitULEB128(idx);
+ Asm->EmitLabelDifference(Entry.getEndSym(), Entry.getBeginSym(), 4);
+
+ emitDebugLocEntryLocation(Entry);
+ }
+ Asm->EmitInt8(dwarf::DW_LLE_end_of_list_entry);
+ }
}
struct ArangeSpan {
@@ -2777,18 +2461,17 @@ struct ArangeSpan {
// address we can tie back to a CU.
void DwarfDebug::emitDebugARanges() {
// Start the dwarf aranges section.
- Asm->OutStreamer
- .SwitchSection(Asm->getObjFileLowering().getDwarfARangesSection());
+ Asm->OutStreamer.SwitchSection(
+ Asm->getObjFileLowering().getDwarfARangesSection());
- typedef DenseMap<CompileUnit *, std::vector<ArangeSpan> > SpansType;
+ typedef DenseMap<DwarfCompileUnit *, std::vector<ArangeSpan> > SpansType;
SpansType Spans;
// Build a list of sections used.
std::vector<const MCSection *> Sections;
- for (SectionMapType::iterator it = SectionMap.begin(); it != SectionMap.end();
- it++) {
- const MCSection *Section = it->first;
+ for (const auto &it : SectionMap) {
+ const MCSection *Section = it.first;
Sections.push_back(Section);
}
@@ -2797,22 +2480,30 @@ void DwarfDebug::emitDebugARanges() {
std::sort(Sections.begin(), Sections.end(), SectionSort);
// Build a set of address spans, sorted by CU.
- for (size_t SecIdx=0;SecIdx<Sections.size();SecIdx++) {
- const MCSection *Section = Sections[SecIdx];
+ for (const MCSection *Section : Sections) {
SmallVector<SymbolCU, 8> &List = SectionMap[Section];
if (List.size() < 2)
continue;
// Sort the symbols by offset within the section.
- SymbolCUSorter sorter(Asm->OutStreamer);
- std::sort(List.begin(), List.end(), sorter);
+ std::sort(List.begin(), List.end(),
+ [&](const SymbolCU &A, const SymbolCU &B) {
+ unsigned IA = A.Sym ? Asm->OutStreamer.GetSymbolOrder(A.Sym) : 0;
+ unsigned IB = B.Sym ? Asm->OutStreamer.GetSymbolOrder(B.Sym) : 0;
+
+ // Symbols with no order assigned should be placed at the end.
+ // (e.g. section end labels)
+ if (IA == 0)
+ return false;
+ if (IB == 0)
+ return true;
+ return IA < IB;
+ });
// If we have no section (e.g. common), just write out
// individual spans for each symbol.
if (Section == NULL) {
- for (size_t n = 0; n < List.size(); n++) {
- const SymbolCU &Cur = List[n];
-
+ for (const SymbolCU &Cur : List) {
ArangeSpan Span;
Span.Start = Cur.Sym;
Span.End = NULL;
@@ -2822,7 +2513,7 @@ void DwarfDebug::emitDebugARanges() {
} else {
// Build spans between each label.
const MCSymbol *StartSym = List[0].Sym;
- for (size_t n = 1; n < List.size(); n++) {
+ for (size_t n = 1, e = List.size(); n < e; n++) {
const SymbolCU &Prev = List[n - 1];
const SymbolCU &Cur = List[n];
@@ -2838,37 +2529,36 @@ void DwarfDebug::emitDebugARanges() {
}
}
- const MCSection *ISec = Asm->getObjFileLowering().getDwarfInfoSection();
unsigned PtrSize = Asm->getDataLayout().getPointerSize();
// Build a list of CUs used.
- std::vector<CompileUnit *> CUs;
- for (SpansType::iterator it = Spans.begin(); it != Spans.end(); it++) {
- CompileUnit *CU = it->first;
+ std::vector<DwarfCompileUnit *> CUs;
+ for (const auto &it : Spans) {
+ DwarfCompileUnit *CU = it.first;
CUs.push_back(CU);
}
// Sort the CU list (again, to ensure consistent output order).
- std::sort(CUs.begin(), CUs.end(), CUSort);
+ std::sort(CUs.begin(), CUs.end(), [](const DwarfUnit *A, const DwarfUnit *B) {
+ return A->getUniqueID() < B->getUniqueID();
+ });
// Emit an arange table for each CU we used.
- for (size_t CUIdx=0;CUIdx<CUs.size();CUIdx++) {
- CompileUnit *CU = CUs[CUIdx];
+ for (DwarfCompileUnit *CU : CUs) {
std::vector<ArangeSpan> &List = Spans[CU];
// Emit size of content not including length itself.
- unsigned ContentSize
- = sizeof(int16_t) // DWARF ARange version number
- + sizeof(int32_t) // Offset of CU in the .debug_info section
- + sizeof(int8_t) // Pointer Size (in bytes)
- + sizeof(int8_t); // Segment Size (in bytes)
+ unsigned ContentSize =
+ sizeof(int16_t) + // DWARF ARange version number
+ sizeof(int32_t) + // Offset of CU in the .debug_info section
+ sizeof(int8_t) + // Pointer Size (in bytes)
+ sizeof(int8_t); // Segment Size (in bytes)
unsigned TupleSize = PtrSize * 2;
// 7.20 in the Dwarf specs requires the table to be aligned to a tuple.
- unsigned Padding = 0;
- while (((sizeof(int32_t) + ContentSize + Padding) % TupleSize) != 0)
- Padding++;
+ unsigned Padding =
+ OffsetToAlignment(sizeof(int32_t) + ContentSize, TupleSize);
ContentSize += Padding;
ContentSize += (List.size() + 1) * TupleSize;
@@ -2879,19 +2569,15 @@ void DwarfDebug::emitDebugARanges() {
Asm->OutStreamer.AddComment("DWARF Arange version number");
Asm->EmitInt16(dwarf::DW_ARANGES_VERSION);
Asm->OutStreamer.AddComment("Offset Into Debug Info Section");
- Asm->EmitSectionOffset(
- Asm->GetTempSymbol(ISec->getLabelBeginName(), CU->getUniqueID()),
- DwarfInfoSectionSym);
+ Asm->EmitSectionOffset(CU->getLocalLabelBegin(), CU->getLocalSectionSym());
Asm->OutStreamer.AddComment("Address Size (in bytes)");
Asm->EmitInt8(PtrSize);
Asm->OutStreamer.AddComment("Segment Size (in bytes)");
Asm->EmitInt8(0);
- for (unsigned n = 0; n < Padding; n++)
- Asm->EmitInt8(0xff);
+ Asm->OutStreamer.EmitFill(Padding, 0xff);
- for (unsigned n = 0; n < List.size(); n++) {
- const ArangeSpan &Span = List[n];
+ for (const ArangeSpan &Span : List) {
Asm->EmitLabelReference(Span.Start, PtrSize);
// Calculate the size as being from the span start to it's end.
@@ -2917,122 +2603,129 @@ void DwarfDebug::emitDebugARanges() {
// Emit visible names into a debug ranges section.
void DwarfDebug::emitDebugRanges() {
// Start the dwarf ranges section.
- Asm->OutStreamer
- .SwitchSection(Asm->getObjFileLowering().getDwarfRangesSection());
+ Asm->OutStreamer.SwitchSection(
+ Asm->getObjFileLowering().getDwarfRangesSection());
+
+ // Size for our labels.
unsigned char Size = Asm->getDataLayout().getPointerSize();
- for (SmallVectorImpl<const MCSymbol *>::iterator
- I = DebugRangeSymbols.begin(), E = DebugRangeSymbols.end();
- I != E; ++I) {
- if (*I)
- Asm->OutStreamer.EmitSymbolValue(const_cast<MCSymbol*>(*I), Size);
- else
+
+ // Grab the specific ranges for the compile units in the module.
+ for (const auto &I : CUMap) {
+ DwarfCompileUnit *TheCU = I.second;
+
+ // Emit a symbol so we can find the beginning of our ranges.
+ Asm->OutStreamer.EmitLabel(TheCU->getLabelRange());
+
+ // Iterate over the misc ranges for the compile units in the module.
+ for (const RangeSpanList &List : TheCU->getRangeLists()) {
+ // Emit our symbol so we can find the beginning of the range.
+ Asm->OutStreamer.EmitLabel(List.getSym());
+
+ for (const RangeSpan &Range : List.getRanges()) {
+ const MCSymbol *Begin = Range.getStart();
+ const MCSymbol *End = Range.getEnd();
+ assert(Begin && "Range without a begin symbol?");
+ assert(End && "Range without an end symbol?");
+ Asm->OutStreamer.EmitSymbolValue(Begin, Size);
+ Asm->OutStreamer.EmitSymbolValue(End, Size);
+ }
+
+ // And terminate the list with two 0 values.
Asm->OutStreamer.EmitIntValue(0, Size);
- }
-}
+ Asm->OutStreamer.EmitIntValue(0, Size);
+ }
-// Emit visible names into a debug macinfo section.
-void DwarfDebug::emitDebugMacInfo() {
- if (const MCSection *LineInfo =
- Asm->getObjFileLowering().getDwarfMacroInfoSection()) {
- // Start the dwarf macinfo section.
- Asm->OutStreamer.SwitchSection(LineInfo);
+ // Now emit a range for the CU itself.
+ if (TheCU->getRanges().size() > 1) {
+ Asm->OutStreamer.EmitLabel(
+ Asm->GetTempSymbol("cu_ranges", TheCU->getUniqueID()));
+ for (const RangeSpan &Range : TheCU->getRanges()) {
+ const MCSymbol *Begin = Range.getStart();
+ const MCSymbol *End = Range.getEnd();
+ assert(Begin && "Range without a begin symbol?");
+ assert(End && "Range without an end symbol?");
+ Asm->OutStreamer.EmitSymbolValue(Begin, Size);
+ Asm->OutStreamer.EmitSymbolValue(End, Size);
+ }
+ // And terminate the list with two 0 values.
+ Asm->OutStreamer.EmitIntValue(0, Size);
+ Asm->OutStreamer.EmitIntValue(0, Size);
+ }
}
}
// DWARF5 Experimental Separate Dwarf emitters.
-// This DIE has the following attributes: DW_AT_comp_dir, DW_AT_stmt_list,
-// DW_AT_low_pc, DW_AT_high_pc, DW_AT_ranges, DW_AT_dwo_name, DW_AT_dwo_id,
-// DW_AT_ranges_base, DW_AT_addr_base.
-CompileUnit *DwarfDebug::constructSkeletonCU(const CompileUnit *CU) {
+void DwarfDebug::initSkeletonUnit(const DwarfUnit *U, DIE *Die,
+ DwarfUnit *NewU) {
+ NewU->addLocalString(Die, dwarf::DW_AT_GNU_dwo_name,
+ U->getCUNode().getSplitDebugFilename());
- DIE *Die = new DIE(dwarf::DW_TAG_compile_unit);
- CompileUnit *NewCU = new CompileUnit(CU->getUniqueID(), Die, CU->getNode(),
- Asm, this, &SkeletonHolder);
-
- NewCU->addLocalString(Die, dwarf::DW_AT_GNU_dwo_name,
- CU->getNode().getSplitDebugFilename());
-
- // Relocate to the beginning of the addr_base section, else 0 for the
- // beginning of the one for this compile unit.
- if (Asm->MAI->doesDwarfUseRelocationsAcrossSections())
- NewCU->addLabel(Die, dwarf::DW_AT_GNU_addr_base, dwarf::DW_FORM_sec_offset,
- DwarfAddrSectionSym);
- else
- NewCU->addUInt(Die, dwarf::DW_AT_GNU_addr_base,
- dwarf::DW_FORM_sec_offset, 0);
+ if (!CompilationDir.empty())
+ NewU->addLocalString(Die, dwarf::DW_AT_comp_dir, CompilationDir);
- // 2.17.1 requires that we use DW_AT_low_pc for a single entry point
- // into an entity. We're using 0, or a NULL label for this.
- NewCU->addUInt(Die, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr, 0);
+ addGnuPubAttributes(NewU, Die);
- // DW_AT_stmt_list is a offset of line number information for this
- // compile unit in debug_line section.
- // FIXME: Should handle multiple compile units.
- if (Asm->MAI->doesDwarfUseRelocationsAcrossSections())
- NewCU->addLabel(Die, dwarf::DW_AT_stmt_list, dwarf::DW_FORM_sec_offset,
- DwarfLineSectionSym);
- else
- NewCU->addUInt(Die, dwarf::DW_AT_stmt_list, dwarf::DW_FORM_sec_offset, 0);
-
- if (!CompilationDir.empty())
- NewCU->addLocalString(Die, dwarf::DW_AT_comp_dir, CompilationDir);
+ SkeletonHolder.addUnit(NewU);
+}
- // Flags to let the linker know we have emitted new style pubnames.
- if (GenerateGnuPubSections) {
- if (Asm->MAI->doesDwarfUseRelocationsAcrossSections())
- NewCU->addLabel(Die, dwarf::DW_AT_GNU_pubnames, dwarf::DW_FORM_sec_offset,
- Asm->GetTempSymbol("gnu_pubnames", NewCU->getUniqueID()));
- else
- NewCU->addDelta(Die, dwarf::DW_AT_GNU_pubnames, dwarf::DW_FORM_data4,
- Asm->GetTempSymbol("gnu_pubnames", NewCU->getUniqueID()),
- DwarfGnuPubNamesSectionSym);
+// This DIE has the following attributes: DW_AT_comp_dir, DW_AT_stmt_list,
+// DW_AT_low_pc, DW_AT_high_pc, DW_AT_ranges, DW_AT_dwo_name, DW_AT_dwo_id,
+// DW_AT_addr_base, DW_AT_ranges_base.
+DwarfCompileUnit *DwarfDebug::constructSkeletonCU(const DwarfCompileUnit *CU) {
- if (Asm->MAI->doesDwarfUseRelocationsAcrossSections())
- NewCU->addLabel(Die, dwarf::DW_AT_GNU_pubtypes, dwarf::DW_FORM_sec_offset,
- Asm->GetTempSymbol("gnu_pubtypes", NewCU->getUniqueID()));
- else
- NewCU->addDelta(Die, dwarf::DW_AT_GNU_pubtypes, dwarf::DW_FORM_data4,
- Asm->GetTempSymbol("gnu_pubtypes", NewCU->getUniqueID()),
- DwarfGnuPubTypesSectionSym);
- }
+ DIE *Die = new DIE(dwarf::DW_TAG_compile_unit);
+ DwarfCompileUnit *NewCU = new DwarfCompileUnit(
+ CU->getUniqueID(), Die, CU->getCUNode(), Asm, this, &SkeletonHolder);
+ NewCU->initSection(Asm->getObjFileLowering().getDwarfInfoSection(),
+ DwarfInfoSectionSym);
- // Flag if we've emitted any ranges and their location for the compile unit.
- if (DebugRangeSymbols.size()) {
- if (Asm->MAI->doesDwarfUseRelocationsAcrossSections())
- NewCU->addLabel(Die, dwarf::DW_AT_GNU_ranges_base,
- dwarf::DW_FORM_sec_offset, DwarfDebugRangeSectionSym);
- else
- NewCU->addUInt(Die, dwarf::DW_AT_GNU_ranges_base, dwarf::DW_FORM_data4,
- 0);
- }
+ NewCU->initStmtList(DwarfLineSectionSym);
- SkeletonHolder.addUnit(NewCU);
- SkeletonCUs.push_back(NewCU);
+ initSkeletonUnit(CU, Die, NewCU);
return NewCU;
}
-void DwarfDebug::emitSkeletonAbbrevs(const MCSection *Section) {
- assert(useSplitDwarf() && "No split dwarf debug info?");
- emitAbbrevs(Section, &SkeletonAbbrevs);
+// This DIE has the following attributes: DW_AT_comp_dir, DW_AT_dwo_name,
+// DW_AT_addr_base.
+DwarfTypeUnit *DwarfDebug::constructSkeletonTU(DwarfTypeUnit *TU) {
+ DwarfCompileUnit &CU = static_cast<DwarfCompileUnit &>(
+ *SkeletonHolder.getUnits()[TU->getCU().getUniqueID()]);
+
+ DIE *Die = new DIE(dwarf::DW_TAG_type_unit);
+ DwarfTypeUnit *NewTU =
+ new DwarfTypeUnit(TU->getUniqueID(), Die, CU, Asm, this, &SkeletonHolder);
+ NewTU->setTypeSignature(TU->getTypeSignature());
+ NewTU->setType(NULL);
+ NewTU->initSection(
+ Asm->getObjFileLowering().getDwarfTypesSection(TU->getTypeSignature()));
+
+ initSkeletonUnit(TU, Die, NewTU);
+ return NewTU;
}
// Emit the .debug_info.dwo section for separated dwarf. This contains the
// compile units that would normally be in debug_info.
void DwarfDebug::emitDebugInfoDWO() {
assert(useSplitDwarf() && "No split dwarf debug info?");
- InfoHolder.emitUnits(this, Asm->getObjFileLowering().getDwarfInfoDWOSection(),
- Asm->getObjFileLowering().getDwarfAbbrevDWOSection(),
- DwarfAbbrevDWOSectionSym);
+ // Don't pass an abbrev symbol, using a constant zero instead so as not to
+ // emit relocations into the dwo file.
+ InfoHolder.emitUnits(this, /* AbbrevSymbol */nullptr);
}
// Emit the .debug_abbrev.dwo section for separated dwarf. This contains the
// abbreviations for the .debug_info.dwo section.
void DwarfDebug::emitDebugAbbrevDWO() {
assert(useSplitDwarf() && "No split dwarf?");
- emitAbbrevs(Asm->getObjFileLowering().getDwarfAbbrevDWOSection(),
- &Abbreviations);
+ InfoHolder.emitAbbrevs(Asm->getObjFileLowering().getDwarfAbbrevDWOSection());
+}
+
+void DwarfDebug::emitDebugLineDWO() {
+ assert(useSplitDwarf() && "No split dwarf?");
+ Asm->OutStreamer.SwitchSection(
+ Asm->getObjFileLowering().getDwarfLineDWOSection());
+ SplitTypeUnitFileTable.Emit(Asm->OutStreamer);
}
// Emit the .debug_str.dwo section for separated dwarf. This contains the
@@ -3040,9 +2733,75 @@ void DwarfDebug::emitDebugAbbrevDWO() {
// sections.
void DwarfDebug::emitDebugStrDWO() {
assert(useSplitDwarf() && "No split dwarf?");
- const MCSection *OffSec = Asm->getObjFileLowering()
- .getDwarfStrOffDWOSection();
+ const MCSection *OffSec =
+ Asm->getObjFileLowering().getDwarfStrOffDWOSection();
const MCSymbol *StrSym = DwarfStrSectionSym;
InfoHolder.emitStrings(Asm->getObjFileLowering().getDwarfStrDWOSection(),
OffSec, StrSym);
}
+
+MCDwarfDwoLineTable *DwarfDebug::getDwoLineTable(const DwarfCompileUnit &CU) {
+ if (!useSplitDwarf())
+ return nullptr;
+ if (SingleCU)
+ SplitTypeUnitFileTable.setCompilationDir(CU.getCUNode().getDirectory());
+ return &SplitTypeUnitFileTable;
+}
+
+void DwarfDebug::addDwarfTypeUnitType(DwarfCompileUnit &CU,
+ StringRef Identifier, DIE *RefDie,
+ DICompositeType CTy) {
+ // Flag the type unit reference as a declaration so that if it contains
+ // members (implicit special members, static data member definitions, member
+ // declarations for definitions in this CU, etc) consumers don't get confused
+ // and think this is a full definition.
+ CU.addFlag(RefDie, dwarf::DW_AT_declaration);
+
+ const DwarfTypeUnit *&TU = DwarfTypeUnits[CTy];
+ if (TU) {
+ CU.addDIETypeSignature(RefDie, *TU);
+ return;
+ }
+
+ DIE *UnitDie = new DIE(dwarf::DW_TAG_type_unit);
+ DwarfTypeUnit *NewTU =
+ new DwarfTypeUnit(InfoHolder.getUnits().size(), UnitDie, CU, Asm, this,
+ &InfoHolder, getDwoLineTable(CU));
+ TU = NewTU;
+ InfoHolder.addUnit(NewTU);
+
+ NewTU->addUInt(UnitDie, dwarf::DW_AT_language, dwarf::DW_FORM_data2,
+ CU.getLanguage());
+
+ MD5 Hash;
+ Hash.update(Identifier);
+ // ... take the least significant 8 bytes and return those. Our MD5
+ // implementation always returns its results in little endian, swap bytes
+ // appropriately.
+ MD5::MD5Result Result;
+ Hash.final(Result);
+ uint64_t Signature = *reinterpret_cast<support::ulittle64_t *>(Result + 8);
+ NewTU->setTypeSignature(Signature);
+ if (useSplitDwarf())
+ NewTU->setSkeleton(constructSkeletonTU(NewTU));
+ else
+ CU.applyStmtList(*UnitDie);
+
+ NewTU->setType(NewTU->createTypeDIE(CTy));
+
+ NewTU->initSection(
+ useSplitDwarf()
+ ? Asm->getObjFileLowering().getDwarfTypesDWOSection(Signature)
+ : Asm->getObjFileLowering().getDwarfTypesSection(Signature));
+
+ CU.addDIETypeSignature(RefDie, *NewTU);
+}
+
+void DwarfDebug::attachLowHighPC(DwarfCompileUnit *Unit, DIE *D,
+ MCSymbol *Begin, MCSymbol *End) {
+ Unit->addLabelAddress(D, dwarf::DW_AT_low_pc, Begin);
+ if (DwarfVersion < 4)
+ Unit->addLabelAddress(D, dwarf::DW_AT_high_pc, End);
+ else
+ Unit->addLabelDelta(D, dwarf::DW_AT_high_pc, End, Begin);
+}
diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.h b/lib/CodeGen/AsmPrinter/DwarfDebug.h
index cebac39a19..da708f510c 100644
--- a/lib/CodeGen/AsmPrinter/DwarfDebug.h
+++ b/lib/CodeGen/AsmPrinter/DwarfDebug.h
@@ -14,44 +14,44 @@
#ifndef CODEGEN_ASMPRINTER_DWARFDEBUG_H__
#define CODEGEN_ASMPRINTER_DWARFDEBUG_H__
+#include "AsmPrinterHandler.h"
#include "DIE.h"
+#include "DebugLocEntry.h"
+#include "DebugLocList.h"
#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/FoldingSet.h"
-#include "llvm/ADT/SetVector.h"
+#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/StringMap.h"
-#include "llvm/CodeGen/AsmPrinter.h"
+#include "llvm/ADT/FoldingSet.h"
#include "llvm/CodeGen/LexicalScopes.h"
-#include "llvm/DebugInfo.h"
+#include "llvm/IR/DebugInfo.h"
+#include "llvm/IR/DebugLoc.h"
#include "llvm/MC/MachineLocation.h"
+#include "llvm/MC/MCDwarf.h"
#include "llvm/Support/Allocator.h"
-#include "llvm/Support/DebugLoc.h"
namespace llvm {
-class CompileUnit;
+class AsmPrinter;
+class ByteStreamer;
class ConstantInt;
class ConstantFP;
-class DbgVariable;
-class MachineFrameInfo;
+class DwarfCompileUnit;
+class DwarfDebug;
+class DwarfTypeUnit;
+class DwarfUnit;
class MachineModuleInfo;
-class MachineOperand;
-class MCAsmInfo;
-class DIEAbbrev;
-class DIE;
-class DIEBlock;
-class DIEEntry;
//===----------------------------------------------------------------------===//
/// \brief This class is used to record source line correspondence.
class SrcLineInfo {
- unsigned Line; // Source line number.
- unsigned Column; // Source column.
- unsigned SourceID; // Source ID number.
- MCSymbol *Label; // Label in code ID number.
+ unsigned Line; // Source line number.
+ unsigned Column; // Source column.
+ unsigned SourceID; // Source ID number.
+ MCSymbol *Label; // Label in code ID number.
public:
SrcLineInfo(unsigned L, unsigned C, unsigned S, MCSymbol *label)
- : Line(L), Column(C), SourceID(S), Label(label) {}
+ : Line(L), Column(C), SourceID(S), Label(label) {}
// Accessors
unsigned getLine() const { return Line; }
@@ -60,124 +60,44 @@ public:
MCSymbol *getLabel() const { return Label; }
};
-/// \brief This struct describes location entries emitted in the .debug_loc
-/// section.
-class DotDebugLocEntry {
- // Begin and end symbols for the address range that this location is valid.
- const MCSymbol *Begin;
- const MCSymbol *End;
-
- // Type of entry that this represents.
- enum EntryType {
- E_Location,
- E_Integer,
- E_ConstantFP,
- E_ConstantInt
- };
- enum EntryType EntryKind;
-
- union {
- int64_t Int;
- const ConstantFP *CFP;
- const ConstantInt *CIP;
- } Constants;
-
- // The location in the machine frame.
- MachineLocation Loc;
-
- // The variable to which this location entry corresponds.
- const MDNode *Variable;
-
- // Whether this location has been merged.
- bool Merged;
-
-public:
- DotDebugLocEntry() : Begin(0), End(0), Variable(0), Merged(false) {
- Constants.Int = 0;
- }
- DotDebugLocEntry(const MCSymbol *B, const MCSymbol *E, MachineLocation &L,
- const MDNode *V)
- : Begin(B), End(E), Loc(L), Variable(V), Merged(false) {
- Constants.Int = 0;
- EntryKind = E_Location;
- }
- DotDebugLocEntry(const MCSymbol *B, const MCSymbol *E, int64_t i)
- : Begin(B), End(E), Variable(0), Merged(false) {
- Constants.Int = i;
- EntryKind = E_Integer;
- }
- DotDebugLocEntry(const MCSymbol *B, const MCSymbol *E, const ConstantFP *FPtr)
- : Begin(B), End(E), Variable(0), Merged(false) {
- Constants.CFP = FPtr;
- EntryKind = E_ConstantFP;
- }
- DotDebugLocEntry(const MCSymbol *B, const MCSymbol *E,
- const ConstantInt *IPtr)
- : Begin(B), End(E), Variable(0), Merged(false) {
- Constants.CIP = IPtr;
- EntryKind = E_ConstantInt;
- }
-
- /// \brief Empty entries are also used as a trigger to emit temp label. Such
- /// labels are referenced is used to find debug_loc offset for a given DIE.
- bool isEmpty() { return Begin == 0 && End == 0; }
- bool isMerged() { return Merged; }
- void Merge(DotDebugLocEntry *Next) {
- if (!(Begin && Loc == Next->Loc && End == Next->Begin))
- return;
- Next->Begin = Begin;
- Merged = true;
- }
- bool isLocation() const { return EntryKind == E_Location; }
- bool isInt() const { return EntryKind == E_Integer; }
- bool isConstantFP() const { return EntryKind == E_ConstantFP; }
- bool isConstantInt() const { return EntryKind == E_ConstantInt; }
- int64_t getInt() const { return Constants.Int; }
- const ConstantFP *getConstantFP() const { return Constants.CFP; }
- const ConstantInt *getConstantInt() const { return Constants.CIP; }
- const MDNode *getVariable() const { return Variable; }
- const MCSymbol *getBeginSym() const { return Begin; }
- const MCSymbol *getEndSym() const { return End; }
- MachineLocation getLoc() const { return Loc; }
-};
-
//===----------------------------------------------------------------------===//
/// \brief This class is used to track local variable information.
class DbgVariable {
- DIVariable Var; // Variable Descriptor.
- DIE *TheDIE; // Variable DIE.
- unsigned DotDebugLocOffset; // Offset in DotDebugLocEntries.
- DbgVariable *AbsVar; // Corresponding Abstract variable, if any.
- const MachineInstr *MInsn; // DBG_VALUE instruction of the variable.
+ DIVariable Var; // Variable Descriptor.
+ DIE *TheDIE; // Variable DIE.
+ unsigned DotDebugLocOffset; // Offset in DotDebugLocEntries.
+ DbgVariable *AbsVar; // Corresponding Abstract variable, if any.
+ const MachineInstr *MInsn; // DBG_VALUE instruction of the variable.
int FrameIndex;
DwarfDebug *DD;
+
public:
// AbsVar may be NULL.
DbgVariable(DIVariable V, DbgVariable *AV, DwarfDebug *DD)
- : Var(V), TheDIE(0), DotDebugLocOffset(~0U), AbsVar(AV), MInsn(0),
- FrameIndex(~0), DD(DD) {}
+ : Var(V), TheDIE(0), DotDebugLocOffset(~0U), AbsVar(AV), MInsn(0),
+ FrameIndex(~0), DD(DD) {}
// Accessors.
- DIVariable getVariable() const { return Var; }
- void setDIE(DIE *D) { TheDIE = D; }
- DIE *getDIE() const { return TheDIE; }
- void setDotDebugLocOffset(unsigned O) { DotDebugLocOffset = O; }
- unsigned getDotDebugLocOffset() const { return DotDebugLocOffset; }
- StringRef getName() const { return Var.getName(); }
+ DIVariable getVariable() const { return Var; }
+ void setDIE(DIE *D) { TheDIE = D; }
+ DIE *getDIE() const { return TheDIE; }
+ void setDotDebugLocOffset(unsigned O) { DotDebugLocOffset = O; }
+ unsigned getDotDebugLocOffset() const { return DotDebugLocOffset; }
+ StringRef getName() const { return Var.getName(); }
DbgVariable *getAbstractVariable() const { return AbsVar; }
- const MachineInstr *getMInsn() const { return MInsn; }
- void setMInsn(const MachineInstr *M) { MInsn = M; }
- int getFrameIndex() const { return FrameIndex; }
- void setFrameIndex(int FI) { FrameIndex = FI; }
+ const MachineInstr *getMInsn() const { return MInsn; }
+ void setMInsn(const MachineInstr *M) { MInsn = M; }
+ int getFrameIndex() const { return FrameIndex; }
+ void setFrameIndex(int FI) { FrameIndex = FI; }
// Translate tag to proper Dwarf tag.
- uint16_t getTag() const {
+ uint16_t getTag() const {
if (Var.getTag() == dwarf::DW_TAG_arg_variable)
return dwarf::DW_TAG_formal_parameter;
return dwarf::DW_TAG_variable;
}
/// \brief Return true if DbgVariable is artificial.
- bool isArtificial() const {
+ bool isArtificial() const {
if (Var.isArtificial())
return true;
if (getType().isArtificial())
@@ -185,7 +105,7 @@ public:
return false;
}
- bool isObjectPointer() const {
+ bool isObjectPointer() const {
if (Var.isObjectPointer())
return true;
if (getType().isObjectPointer())
@@ -193,21 +113,16 @@ public:
return false;
}
- bool variableHasComplexAddress() const {
+ bool variableHasComplexAddress() const {
assert(Var.isVariable() && "Invalid complex DbgVariable!");
return Var.hasComplexAddress();
}
- bool isBlockByrefVariable() const {
- assert(Var.isVariable() && "Invalid complex DbgVariable!");
- return Var.isBlockByrefVariable();
- }
- unsigned getNumAddrElements() const {
+ bool isBlockByrefVariable() const;
+ unsigned getNumAddrElements() const {
assert(Var.isVariable() && "Invalid complex DbgVariable!");
return Var.getNumAddrElements();
}
- uint64_t getAddrElement(unsigned i) const {
- return Var.getAddrElement(i);
- }
+ uint64_t getAddrElement(unsigned i) const { return Var.getAddrElement(i); }
DIType getType() const;
private:
@@ -217,43 +132,50 @@ private:
};
/// \brief Collects and handles information specific to a particular
-/// collection of units.
-class DwarfUnits {
+/// collection of units. This collection represents all of the units
+/// that will be ultimately output into a single object file.
+class DwarfFile {
// Target of Dwarf emission, used for sizing of abbreviations.
AsmPrinter *Asm;
// Used to uniquely define abbreviations.
- FoldingSet<DIEAbbrev> *AbbreviationsSet;
+ FoldingSet<DIEAbbrev> AbbreviationsSet;
// A list of all the unique abbreviations in use.
- std::vector<DIEAbbrev *> &Abbreviations;
+ std::vector<DIEAbbrev *> Abbreviations;
// A pointer to all units in the section.
- SmallVector<CompileUnit *, 1> CUs;
+ SmallVector<DwarfUnit *, 1> CUs;
// Collection of strings for this unit and assorted symbols.
// A String->Symbol mapping of strings used by indirect
// references.
- typedef StringMap<std::pair<MCSymbol*, unsigned>,
- BumpPtrAllocator&> StrPool;
+ typedef StringMap<std::pair<MCSymbol *, unsigned>, BumpPtrAllocator &>
+ StrPool;
StrPool StringPool;
unsigned NextStringPoolNumber;
std::string StringPref;
+ struct AddressPoolEntry {
+ unsigned Number;
+ bool TLS;
+ AddressPoolEntry(unsigned Number, bool TLS) : Number(Number), TLS(TLS) {}
+ };
// Collection of addresses for this unit and assorted labels.
// A Symbol->unsigned mapping of addresses used by indirect
// references.
- typedef DenseMap<const MCExpr *, unsigned> AddrPool;
+ typedef DenseMap<const MCSymbol *, AddressPoolEntry> AddrPool;
AddrPool AddressPool;
unsigned NextAddrPoolNumber;
public:
- DwarfUnits(AsmPrinter *AP, FoldingSet<DIEAbbrev> *AS,
- std::vector<DIEAbbrev *> &A, const char *Pref,
- BumpPtrAllocator &DA)
- : Asm(AP), AbbreviationsSet(AS), Abbreviations(A), StringPool(DA),
- NextStringPoolNumber(0), StringPref(Pref), AddressPool(),
- NextAddrPoolNumber(0) {}
+ DwarfFile(AsmPrinter *AP, const char *Pref, BumpPtrAllocator &DA)
+ : Asm(AP), StringPool(DA), NextStringPoolNumber(0), StringPref(Pref),
+ AddressPool(), NextAddrPoolNumber(0) {}
+
+ ~DwarfFile();
+
+ const SmallVectorImpl<DwarfUnit *> &getUnits() { return CUs; }
/// \brief Compute the size and offset of a DIE given an incoming Offset.
unsigned computeSizeAndOffset(DIE *Die, unsigned Offset);
@@ -265,12 +187,14 @@ public:
void assignAbbrevNumber(DIEAbbrev &Abbrev);
/// \brief Add a unit to the list of CUs.
- void addUnit(CompileUnit *CU) { CUs.push_back(CU); }
+ void addUnit(DwarfUnit *CU) { CUs.push_back(CU); }
/// \brief Emit all of the units to the section listed with the given
/// abbreviation section.
- void emitUnits(DwarfDebug *DD, const MCSection *USection,
- const MCSection *ASection, const MCSymbol *ASectionSym);
+ void emitUnits(DwarfDebug *DD, const MCSymbol *ASectionSym);
+
+ /// \brief Emit a set of abbreviations to the specific section.
+ void emitAbbrevs(const MCSection *);
/// \brief Emit all of the strings to the section given.
void emitStrings(const MCSection *StrSection, const MCSection *OffsetSection,
@@ -295,8 +219,7 @@ public:
/// \brief Returns the index into the address pool with the given
/// label/symbol.
- unsigned getAddrPoolIndex(const MCExpr *Sym);
- unsigned getAddrPoolIndex(const MCSymbol *Sym);
+ unsigned getAddrPoolIndex(const MCSymbol *Sym, bool TLS = false);
/// \brief Returns the address pool.
AddrPool *getAddrPool() { return &AddressPool; }
@@ -304,13 +227,13 @@ public:
/// \brief Helper used to pair up a symbol and its DWARF compile unit.
struct SymbolCU {
- SymbolCU(CompileUnit *CU, const MCSymbol *Sym) : Sym(Sym), CU(CU) {}
+ SymbolCU(DwarfCompileUnit *CU, const MCSymbol *Sym) : Sym(Sym), CU(CU) {}
const MCSymbol *Sym;
- CompileUnit *CU;
+ DwarfCompileUnit *CU;
};
/// \brief Collects and handles dwarf debug information.
-class DwarfDebug {
+class DwarfDebug : public AsmPrinterHandler {
// Target of Dwarf emission.
AsmPrinter *Asm;
@@ -320,40 +243,31 @@ class DwarfDebug {
// All DIEValues are allocated through this allocator.
BumpPtrAllocator DIEValueAllocator;
- // Handle to the a compile unit used for the inline extension handling.
- CompileUnit *FirstCU;
+ // Handle to the compile unit used for the inline extension handling,
+ // this is just so that the DIEValue allocator has a place to store
+ // the particular elements.
+ // FIXME: Store these off of DwarfDebug instead?
+ DwarfCompileUnit *FirstCU;
- // Maps MDNode with its corresponding CompileUnit.
- DenseMap <const MDNode *, CompileUnit *> CUMap;
+ // Maps MDNode with its corresponding DwarfCompileUnit.
+ MapVector<const MDNode *, DwarfCompileUnit *> CUMap;
- // Maps subprogram MDNode with its corresponding CompileUnit.
- DenseMap <const MDNode *, CompileUnit *> SPMap;
+ // Maps subprogram MDNode with its corresponding DwarfCompileUnit.
+ DenseMap<const MDNode *, DwarfCompileUnit *> SPMap;
- // Maps a CU DIE with its corresponding CompileUnit.
- DenseMap <const DIE *, CompileUnit *> CUDieMap;
+ // Maps a CU DIE with its corresponding DwarfCompileUnit.
+ DenseMap<const DIE *, DwarfCompileUnit *> CUDieMap;
- /// Maps MDNodes for type sysstem with the corresponding DIEs. These DIEs can
+ /// 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
- /// of in CompileUnit.
+ /// of in DwarfCompileUnit.
DenseMap<const MDNode *, DIE *> MDTypeNodeToDieMap;
- // Used to uniquely define abbreviations.
- FoldingSet<DIEAbbrev> AbbreviationsSet;
-
- // A list of all the unique abbreviations in use.
- std::vector<DIEAbbrev *> Abbreviations;
-
- // Stores the current file ID for a given compile unit.
- DenseMap <unsigned, unsigned> FileIDCUMap;
- // Source id map, i.e. CUID, source filename and directory,
- // separated by a zero byte, mapped to a unique id.
- StringMap<unsigned, BumpPtrAllocator&> SourceIdMap;
-
// List of all labels used in aranges generation.
std::vector<SymbolCU> ArangeLabels;
// Size of each symbol emitted (for those symbols that have a specific size).
- DenseMap <const MCSymbol *, uint64_t> SymSize;
+ DenseMap<const MCSymbol *, uint64_t> SymSize;
// Provides a unique id per text section.
typedef DenseMap<const MCSection *, SmallVector<SymbolCU, 8> > SectionMapType;
@@ -368,15 +282,16 @@ class DwarfDebug {
DenseMap<const MDNode *, DIE *> AbstractSPDies;
// Collection of dbg variables of a scope.
- typedef DenseMap<LexicalScope *,
- SmallVector<DbgVariable *, 8> > ScopeVariablesMap;
+ typedef DenseMap<LexicalScope *, SmallVector<DbgVariable *, 8> >
+ ScopeVariablesMap;
ScopeVariablesMap ScopeVariables;
// Collection of abstract variables.
DenseMap<const MDNode *, DbgVariable *> AbstractVariables;
- // Collection of DotDebugLocEntry.
- SmallVector<DotDebugLocEntry, 4> DotDebugLocEntries;
+ // Collection of DebugLocEntry. Stored in a linked list so that DIELocLists
+ // can refer to them in spite of insertions into this list.
+ SmallVector<DebugLocList, 4> DotDebugLocEntries;
// Collection of subprogram DIEs that are marked (at the end of the module)
// as DW_AT_inline.
@@ -394,17 +309,15 @@ class DwarfDebug {
// Every user variable mentioned by a DBG_VALUE instruction in order of
// appearance.
- SmallVector<const MDNode*, 8> UserVariables;
+ SmallVector<const MDNode *, 8> UserVariables;
// For each user variable, keep a list of DBG_VALUE instructions in order.
// The list can also contain normal instructions that clobber the previous
// DBG_VALUE.
- typedef DenseMap<const MDNode*, SmallVector<const MachineInstr*, 4> >
- DbgValueHistoryMap;
+ typedef DenseMap<const MDNode *, SmallVector<const MachineInstr *, 4> >
+ DbgValueHistoryMap;
DbgValueHistoryMap DbgValues;
- SmallVector<const MCSymbol *, 8> DebugRangeSymbols;
-
// Previous instruction's location information. This is used to determine
// label location to indicate scope boundries in dwarf debug info.
DebugLoc PrevInstLoc;
@@ -414,6 +327,19 @@ class DwarfDebug {
// body.
DebugLoc PrologEndLoc;
+ // If nonnull, stores the current machine function we're processing.
+ const MachineFunction *CurFn;
+
+ // If nonnull, stores the current machine instruction we're processing.
+ const MachineInstr *CurMI;
+
+ // If nonnull, stores the section that the previous function was allocated to
+ // emitting.
+ const MCSection *PrevSection;
+
+ // If nonnull, stores the CU in which the previous subprogram was contained.
+ const DwarfCompileUnit *PrevCU;
+
// Section Symbols: these are assembler temporary labels that are emitted at
// the beginning of each supported dwarf section. These are used to form
// section offsets and are created by EmitSectionLabels.
@@ -421,36 +347,48 @@ class DwarfDebug {
MCSymbol *DwarfStrSectionSym, *TextSectionSym, *DwarfDebugRangeSectionSym;
MCSymbol *DwarfDebugLocSectionSym, *DwarfLineSectionSym, *DwarfAddrSectionSym;
MCSymbol *FunctionBeginSym, *FunctionEndSym;
- MCSymbol *DwarfAbbrevDWOSectionSym, *DwarfStrDWOSectionSym;
+ MCSymbol *DwarfInfoDWOSectionSym, *DwarfAbbrevDWOSectionSym;
+ MCSymbol *DwarfStrDWOSectionSym;
MCSymbol *DwarfGnuPubNamesSectionSym, *DwarfGnuPubTypesSectionSym;
// As an optimization, there is no need to emit an entry in the directory
// table for the same directory as DW_AT_comp_dir.
StringRef CompilationDir;
- // Counter for assigning globally unique IDs for CUs.
- unsigned GlobalCUIndexCount;
+ // Counter for assigning globally unique IDs for ranges.
+ unsigned GlobalRangeCount;
// Holder for the file specific debug information.
- DwarfUnits InfoHolder;
+ DwarfFile InfoHolder;
// Holders for the various debug information flags that we might need to
// have exposed. See accessor functions below for description.
// Holder for imported entities.
typedef SmallVector<std::pair<const MDNode *, const MDNode *>, 32>
- ImportedEntityMap;
+ ImportedEntityMap;
ImportedEntityMap ScopesWithImportedEntities;
- // Holder for types that are going to be extracted out into a type unit.
- std::vector<DIE *> TypeUnits;
+ // Map from MDNodes for user-defined types to the type units that describe
+ // them.
+ DenseMap<const MDNode *, const DwarfTypeUnit *> DwarfTypeUnits;
// Whether to emit the pubnames/pubtypes sections.
bool HasDwarfPubSections;
+ // Whether or not to use AT_ranges for compilation units.
+ bool HasCURanges;
+
+ // Whether we emitted a function into a section other than the default
+ // text.
+ bool UsedNonDefaultText;
+
// Version of dwarf we're emitting.
unsigned DwarfVersion;
+ // Maps from a type identifier to the actual MDNode.
+ DITypeIdentifierMap TypeIdentifierMap;
+
// DWARF5 Experimental Options
bool HasDwarfAccelTables;
bool HasSplitDwarf;
@@ -460,25 +398,27 @@ class DwarfDebug {
// original object file, rather than things that are meant
// to be in the .dwo sections.
- // The CUs left in the original object file for separated debug info.
- SmallVector<CompileUnit *, 1> SkeletonCUs;
-
- // Used to uniquely define abbreviations for the skeleton emission.
- FoldingSet<DIEAbbrev> SkeletonAbbrevSet;
-
- // A list of all the unique abbreviations in use.
- std::vector<DIEAbbrev *> SkeletonAbbrevs;
-
// Holder for the skeleton information.
- DwarfUnits SkeletonHolder;
+ DwarfFile SkeletonHolder;
- // Maps from a type identifier to the actual MDNode.
- DITypeIdentifierMap TypeIdentifierMap;
+ /// Store file names for type units under fission in a line table header that
+ /// will be emitted into debug_line.dwo.
+ // FIXME: replace this with a map from comp_dir to table so that we can emit
+ // multiple tables during LTO each of which uses directory 0, referencing the
+ // comp_dir of all the type units that use it.
+ MCDwarfDwoLineTable SplitTypeUnitFileTable;
-private:
+ // True iff there are multiple CUs in this module.
+ bool SingleCU;
+
+ MCDwarfDwoLineTable *getDwoLineTable(const DwarfCompileUnit &);
void addScopeVariable(LexicalScope *LS, DbgVariable *Var);
+ const SmallVectorImpl<DwarfUnit *> &getUnits() {
+ return InfoHolder.getUnits();
+ }
+
/// \brief Find abstract variable associated with Var.
DbgVariable *findAbstractVariable(DIVariable &Var, DebugLoc Loc);
@@ -486,24 +426,30 @@ private:
/// DW_AT_low_pc and DW_AT_high_pc attributes. If there are global
/// variables in this scope then create and insert DIEs for these
/// variables.
- DIE *updateSubprogramScopeDIE(CompileUnit *SPCU, DISubprogram SP);
+ DIE *updateSubprogramScopeDIE(DwarfCompileUnit *SPCU, DISubprogram SP);
+
+ /// \brief A helper function to check whether the DIE for a given Scope is
+ /// going to be null.
+ bool isLexicalScopeDIENull(LexicalScope *Scope);
+
+ /// \brief A helper function to construct a RangeSpanList for a given
+ /// lexical scope.
+ void addScopeRangeList(DwarfCompileUnit *TheCU, DIE *ScopeDIE,
+ const SmallVectorImpl<InsnRange> &Range);
/// \brief Construct new DW_TAG_lexical_block for this scope and
/// attach DW_AT_low_pc/DW_AT_high_pc labels.
- DIE *constructLexicalScopeDIE(CompileUnit *TheCU, LexicalScope *Scope);
- /// A helper function to check whether the DIE for a given Scope is going
- /// to be null.
- bool isLexicalScopeDIENull(LexicalScope *Scope);
+ DIE *constructLexicalScopeDIE(DwarfCompileUnit *TheCU, LexicalScope *Scope);
/// \brief This scope represents inlined body of a function. Construct
/// DIE to represent this concrete inlined copy of the function.
- DIE *constructInlinedScopeDIE(CompileUnit *TheCU, LexicalScope *Scope);
+ DIE *constructInlinedScopeDIE(DwarfCompileUnit *TheCU, LexicalScope *Scope);
/// \brief Construct a DIE for this scope.
- DIE *constructScopeDIE(CompileUnit *TheCU, LexicalScope *Scope);
+ DIE *constructScopeDIE(DwarfCompileUnit *TheCU, LexicalScope *Scope);
/// A helper function to create children of a Scope DIE.
- DIE *createScopeChildrenDIE(CompileUnit *TheCU, LexicalScope *Scope,
- SmallVectorImpl<DIE*> &Children);
+ DIE *createScopeChildrenDIE(DwarfCompileUnit *TheCU, LexicalScope *Scope,
+ SmallVectorImpl<DIE *> &Children);
/// \brief Emit initial Dwarf sections with a label at the start of each one.
void emitSectionLabels();
@@ -528,9 +474,6 @@ private:
/// open.
void endSections();
- /// \brief Emit a set of abbreviations to the specific section.
- void emitAbbrevs(const MCSection *, std::vector<DIEAbbrev*> *);
-
/// \brief Emit the debug info section.
void emitDebugInfo();
@@ -566,32 +509,41 @@ private:
/// index.
void emitDebugPubTypes(bool GnuStyle = false);
+ void
+ emitDebugPubSection(bool GnuStyle, const MCSection *PSec, StringRef Name,
+ const StringMap<const DIE *> &(DwarfUnit::*Accessor)()
+ const);
+
/// \brief Emit visible names into a debug str section.
void emitDebugStr();
/// \brief Emit visible names into a debug loc section.
void emitDebugLoc();
+ /// \brief Emit visible names into a debug loc dwo section.
+ void emitDebugLocDWO();
+
/// \brief Emit visible names into a debug aranges section.
void emitDebugARanges();
/// \brief Emit visible names into a debug ranges section.
void emitDebugRanges();
- /// \brief Emit visible names into a debug macinfo section.
- void emitDebugMacInfo();
-
/// \brief Emit inline info using custom format.
void emitDebugInlineInfo();
/// DWARF 5 Experimental Split Dwarf Emitters
+ /// \brief Initialize common features of skeleton units.
+ void initSkeletonUnit(const DwarfUnit *U, DIE *Die, DwarfUnit *NewU);
+
/// \brief Construct the split debug info compile unit for the debug info
/// section.
- CompileUnit *constructSkeletonCU(const CompileUnit *CU);
+ DwarfCompileUnit *constructSkeletonCU(const DwarfCompileUnit *CU);
- /// \brief Emit the local split abbreviations.
- void emitSkeletonAbbrevs(const MCSection *);
+ /// \brief Construct the split debug info compile unit for the debug info
+ /// section.
+ DwarfTypeUnit *constructSkeletonTU(DwarfTypeUnit *TU);
/// \brief Emit the debug info dwo section.
void emitDebugInfoDWO();
@@ -599,27 +551,33 @@ private:
/// \brief Emit the debug abbrev dwo section.
void emitDebugAbbrevDWO();
+ /// \brief Emit the debug line dwo section.
+ void emitDebugLineDWO();
+
/// \brief Emit the debug str dwo section.
void emitDebugStrDWO();
- /// \brief Create new CompileUnit for the given metadata node with tag
+ /// Flags to let the linker know we have emitted new style pubnames. Only
+ /// emit it here if we don't have a skeleton CU for split dwarf.
+ void addGnuPubAttributes(DwarfUnit *U, DIE *D) const;
+
+ /// \brief Create new DwarfCompileUnit for the given metadata node with tag
/// DW_TAG_compile_unit.
- CompileUnit *constructCompileUnit(DICompileUnit DIUnit);
+ DwarfCompileUnit *constructDwarfCompileUnit(DICompileUnit DIUnit);
/// \brief Construct subprogram DIE.
- void constructSubprogramDIE(CompileUnit *TheCU, const MDNode *N);
+ void constructSubprogramDIE(DwarfCompileUnit *TheCU, const MDNode *N);
/// \brief Construct imported_module or imported_declaration DIE.
- void constructImportedEntityDIE(CompileUnit *TheCU, const MDNode *N);
+ void constructImportedEntityDIE(DwarfCompileUnit *TheCU, const MDNode *N);
/// \brief Construct import_module DIE.
- void constructImportedEntityDIE(CompileUnit *TheCU, const MDNode *N,
+ void constructImportedEntityDIE(DwarfCompileUnit *TheCU, const MDNode *N,
DIE *Context);
/// \brief Construct import_module DIE.
- void constructImportedEntityDIE(CompileUnit *TheCU,
- const DIImportedEntity &Module,
- DIE *Context);
+ void constructImportedEntityDIE(DwarfCompileUnit *TheCU,
+ const DIImportedEntity &Module, DIE *Context);
/// \brief Register a source line with debug info. Returns the unique
/// label that was emitted and which provides correspondence to the
@@ -633,21 +591,18 @@ private:
/// \brief If Var is an current function argument that add it in
/// CurrentFnArguments list.
- bool addCurrentFnArgument(const MachineFunction *MF,
- DbgVariable *Var, LexicalScope *Scope);
+ bool addCurrentFnArgument(DbgVariable *Var, LexicalScope *Scope);
/// \brief Populate LexicalScope entries with variables' info.
- void collectVariableInfo(const MachineFunction *,
- SmallPtrSet<const MDNode *, 16> &ProcessedVars);
+ void collectVariableInfo(SmallPtrSet<const MDNode *, 16> &ProcessedVars);
/// \brief Collect variable information from the side table maintained
/// by MMI.
- void collectVariableInfoFromMMITable(const MachineFunction * MF,
- SmallPtrSet<const MDNode *, 16> &P);
+ void collectVariableInfoFromMMITable(SmallPtrSet<const MDNode *, 16> &P);
/// \brief Ensure that a label will be emitted before MI.
void requestLabelBeforeInsn(const MachineInstr *MI) {
- LabelsBeforeInsn.insert(std::make_pair(MI, (MCSymbol*)0));
+ LabelsBeforeInsn.insert(std::make_pair(MI, (MCSymbol *)0));
}
/// \brief Return Label preceding the instruction.
@@ -655,12 +610,15 @@ private:
/// \brief Ensure that a label will be emitted after MI.
void requestLabelAfterInsn(const MachineInstr *MI) {
- LabelsAfterInsn.insert(std::make_pair(MI, (MCSymbol*)0));
+ LabelsAfterInsn.insert(std::make_pair(MI, (MCSymbol *)0));
}
/// \brief Return Label immediately following the instruction.
MCSymbol *getLabelAfterInsn(const MachineInstr *MI);
+ void attachLowHighPC(DwarfCompileUnit *Unit, DIE *D, MCSymbol *Begin,
+ MCSymbol *End);
+
public:
//===--------------------------------------------------------------------===//
// Main entry points.
@@ -679,62 +637,89 @@ public:
void beginModule();
/// \brief Emit all Dwarf sections that should come after the content.
- void endModule();
+ void endModule() override;
/// \brief Gather pre-function debug information.
- void beginFunction(const MachineFunction *MF);
+ void beginFunction(const MachineFunction *MF) override;
/// \brief Gather and emit post-function debug information.
- void endFunction(const MachineFunction *MF);
+ void endFunction(const MachineFunction *MF) override;
/// \brief Process beginning of an instruction.
- void beginInstruction(const MachineInstr *MI);
+ void beginInstruction(const MachineInstr *MI) override;
/// \brief Process end of an instruction.
- void endInstruction(const MachineInstr *MI);
+ void endInstruction() override;
/// \brief Add a DIE to the set of types that we're going to pull into
/// type units.
- void addTypeUnitType(DIE *Die) { TypeUnits.push_back(Die); }
+ void addDwarfTypeUnitType(DwarfCompileUnit &CU, StringRef Identifier,
+ DIE *Die, DICompositeType CTy);
/// \brief Add a label so that arange data can be generated for it.
void addArangeLabel(SymbolCU SCU) { ArangeLabels.push_back(SCU); }
/// \brief For symbols that have a size designated (e.g. common symbols),
/// this tracks that size.
- void setSymbolSize(const MCSymbol *Sym, uint64_t Size) { SymSize[Sym] = Size;}
-
- /// \brief Look up the source id with the given directory and source file
- /// names. If none currently exists, create a new id and insert it in the
- /// SourceIds map.
- unsigned getOrCreateSourceID(StringRef DirName, StringRef FullName,
- unsigned CUID);
+ void setSymbolSize(const MCSymbol *Sym, uint64_t Size) override {
+ SymSize[Sym] = Size;
+ }
/// \brief Recursively Emits a debug information entry.
- void emitDIE(DIE *Die, ArrayRef<DIEAbbrev *> Abbrevs);
+ void emitDIE(DIE *Die);
// Experimental DWARF5 features.
/// \brief Returns whether or not to emit tables that dwarf consumers can
/// use to accelerate lookup.
- bool useDwarfAccelTables() { return HasDwarfAccelTables; }
+ bool useDwarfAccelTables() const { return HasDwarfAccelTables; }
/// \brief Returns whether or not to change the current debug info for the
/// split dwarf proposal support.
- bool useSplitDwarf() { return HasSplitDwarf; }
+ bool useSplitDwarf() const { return HasSplitDwarf; }
/// Returns the Dwarf Version.
unsigned getDwarfVersion() const { return DwarfVersion; }
+ /// Returns the section symbol for the .debug_loc section.
+ MCSymbol *getDebugLocSym() const { return DwarfDebugLocSectionSym; }
+
+ /// Returns the previous section that was emitted into.
+ const MCSection *getPrevSection() const { return PrevSection; }
+
+ /// Returns the previous CU that was being updated
+ const DwarfCompileUnit *getPrevCU() const { return PrevCU; }
+
+ /// Returns the entries for the .debug_loc section.
+ const SmallVectorImpl<DebugLocList> &
+ getDebugLocEntries() const {
+ return DotDebugLocEntries;
+ }
+
+ /// \brief Emit an entry for the debug loc section. This can be used to
+ /// handle an entry that's going to be emitted into the debug loc section.
+ void emitDebugLocEntry(ByteStreamer &Streamer, const DebugLocEntry &Entry);
+
+ /// Emit the location for a debug loc entry, including the size header.
+ void emitDebugLocEntryLocation(const DebugLocEntry &Entry);
+
/// Find the MDNode for the given reference.
template <typename T> T resolve(DIRef<T> Ref) const {
return Ref.resolve(TypeIdentifierMap);
}
+ /// \brief Return the TypeIdentifierMap.
+ const DITypeIdentifierMap &getTypeIdentifierMap() const {
+ return TypeIdentifierMap;
+ }
+
+ /// Find the DwarfCompileUnit for the given CU Die.
+ DwarfCompileUnit *lookupUnit(const DIE *CU) const {
+ return CUDieMap.lookup(CU);
+ }
/// isSubprogramContext - Return true if Context is either a subprogram
/// or another context nested inside a subprogram.
bool isSubprogramContext(const MDNode *Context);
-
};
} // End of namespace llvm
diff --git a/lib/CodeGen/AsmPrinter/DwarfException.cpp b/lib/CodeGen/AsmPrinter/DwarfException.cpp
index 7133458129..113a9e4cd4 100644
--- a/lib/CodeGen/AsmPrinter/DwarfException.cpp
+++ b/lib/CodeGen/AsmPrinter/DwarfException.cpp
@@ -20,6 +20,7 @@
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/IR/DataLayout.h"
+#include "llvm/IR/Mangler.h"
#include "llvm/IR/Module.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCContext.h"
@@ -30,7 +31,7 @@
#include "llvm/Support/Dwarf.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FormattedStream.h"
-#include "llvm/Target/Mangler.h"
+#include "llvm/Support/LEB128.h"
#include "llvm/Target/TargetFrameLowering.h"
#include "llvm/Target/TargetLoweringObjectFile.h"
#include "llvm/Target/TargetOptions.h"
@@ -57,19 +58,6 @@ unsigned DwarfException::SharedTypeIds(const LandingPadInfo *L,
return Count;
}
-/// PadLT - Order landing pads lexicographically by type id.
-bool DwarfException::PadLT(const LandingPadInfo *L, const LandingPadInfo *R) {
- const std::vector<int> &LIds = L->TypeIds, &RIds = R->TypeIds;
- unsigned LSize = LIds.size(), RSize = RIds.size();
- unsigned MinSize = LSize < RSize ? LSize : RSize;
-
- for (unsigned i = 0; i != MinSize; ++i)
- if (LIds[i] != RIds[i])
- return LIds[i] < RIds[i];
-
- return LSize < RSize;
-}
-
/// ComputeActionsTable - Compute the actions table and gather the first action
/// index for each landing pad site.
unsigned DwarfException::
@@ -108,7 +96,7 @@ ComputeActionsTable(const SmallVectorImpl<const LandingPadInfo*> &LandingPads,
for (std::vector<unsigned>::const_iterator
I = FilterIds.begin(), E = FilterIds.end(); I != E; ++I) {
FilterOffsets.push_back(Offset);
- Offset -= MCAsmInfo::getULEB128Size(*I);
+ Offset -= getULEB128Size(*I);
}
FirstActions.reserve(LandingPads.size());
@@ -132,14 +120,12 @@ ComputeActionsTable(const SmallVectorImpl<const LandingPadInfo*> &LandingPads,
unsigned SizePrevIds = PrevLPI->TypeIds.size();
assert(Actions.size());
PrevAction = Actions.size() - 1;
- SizeAction =
- MCAsmInfo::getSLEB128Size(Actions[PrevAction].NextAction) +
- MCAsmInfo::getSLEB128Size(Actions[PrevAction].ValueForTypeID);
+ SizeAction = getSLEB128Size(Actions[PrevAction].NextAction) +
+ getSLEB128Size(Actions[PrevAction].ValueForTypeID);
for (unsigned j = NumShared; j != SizePrevIds; ++j) {
assert(PrevAction != (unsigned)-1 && "PrevAction is invalid!");
- SizeAction -=
- MCAsmInfo::getSLEB128Size(Actions[PrevAction].ValueForTypeID);
+ SizeAction -= getSLEB128Size(Actions[PrevAction].ValueForTypeID);
SizeAction += -Actions[PrevAction].NextAction;
PrevAction = Actions[PrevAction].Previous;
}
@@ -150,10 +136,10 @@ ComputeActionsTable(const SmallVectorImpl<const LandingPadInfo*> &LandingPads,
int TypeID = TypeIds[J];
assert(-1 - TypeID < (int)FilterOffsets.size() && "Unknown filter id!");
int ValueForTypeID = TypeID < 0 ? FilterOffsets[-1 - TypeID] : TypeID;
- unsigned SizeTypeID = MCAsmInfo::getSLEB128Size(ValueForTypeID);
+ unsigned SizeTypeID = getSLEB128Size(ValueForTypeID);
int NextAction = SizeAction ? -(SizeAction + SizeTypeID) : 0;
- SizeAction = SizeTypeID + MCAsmInfo::getSLEB128Size(NextAction);
+ SizeAction = SizeTypeID + getSLEB128Size(NextAction);
SizeSiteActions += SizeAction;
ActionEntry Action = { ValueForTypeID, NextAction, PrevAction };
@@ -242,7 +228,7 @@ ComputeCallSiteTable(SmallVectorImpl<CallSiteEntry> &CallSites,
I != E; ++I) {
for (MachineBasicBlock::const_iterator MI = I->begin(), E = I->end();
MI != E; ++MI) {
- if (!MI->isLabel()) {
+ if (!MI->isEHLabel()) {
if (MI->isCall())
SawPotentiallyThrowing |= !CallToNoUnwindFunction(MI);
continue;
@@ -357,7 +343,10 @@ void DwarfException::EmitExceptionTable() {
for (unsigned i = 0, N = PadInfos.size(); i != N; ++i)
LandingPads.push_back(&PadInfos[i]);
- std::sort(LandingPads.begin(), LandingPads.end(), PadLT);
+ // Order landing pads lexicographically by type id.
+ std::sort(LandingPads.begin(), LandingPads.end(),
+ [](const LandingPadInfo *L,
+ const LandingPadInfo *R) { return L->TypeIds < R->TypeIds; });
// Compute the actions table and gather the first action index for each
// landing pad site.
@@ -401,9 +390,9 @@ void DwarfException::EmitExceptionTable() {
}
for (unsigned i = 0, e = CallSites.size(); i < e; ++i) {
- CallSiteTableLength += MCAsmInfo::getULEB128Size(CallSites[i].Action);
+ CallSiteTableLength += getULEB128Size(CallSites[i].Action);
if (IsSJLJ)
- CallSiteTableLength += MCAsmInfo::getULEB128Size(i);
+ CallSiteTableLength += getULEB128Size(i);
}
// Type infos.
@@ -488,15 +477,14 @@ void DwarfException::EmitExceptionTable() {
// We chose another solution: don't output padding inside the table like GCC
// does, instead output it before the table.
unsigned SizeTypes = TypeInfos.size() * TypeFormatSize;
- unsigned CallSiteTableLengthSize =
- MCAsmInfo::getULEB128Size(CallSiteTableLength);
+ unsigned CallSiteTableLengthSize = getULEB128Size(CallSiteTableLength);
unsigned TTypeBaseOffset =
sizeof(int8_t) + // Call site format
CallSiteTableLengthSize + // Call site table length size
CallSiteTableLength + // Call site table length
SizeActions + // Actions size
SizeTypes;
- unsigned TTypeBaseOffsetSize = MCAsmInfo::getULEB128Size(TTypeBaseOffset);
+ unsigned TTypeBaseOffsetSize = getULEB128Size(TTypeBaseOffset);
unsigned TotalSize =
sizeof(int8_t) + // LPStart format
sizeof(int8_t) + // TType format
@@ -717,20 +705,19 @@ void DwarfException::EmitTypeInfos(unsigned TTypeEncoding) {
}
}
-/// EndModule - Emit all exception information that should come after the
+/// endModule - Emit all exception information that should come after the
/// content.
-void DwarfException::EndModule() {
+void DwarfException::endModule() {
llvm_unreachable("Should be implemented");
}
-/// BeginFunction - Gather pre-function exception information. Assumes it's
+/// beginFunction - Gather pre-function exception information. Assumes it's
/// being emitted immediately after the function entry point.
-void DwarfException::BeginFunction(const MachineFunction *MF) {
+void DwarfException::beginFunction(const MachineFunction *MF) {
llvm_unreachable("Should be implemented");
}
-/// EndFunction - Gather and emit post-function exception information.
-///
-void DwarfException::EndFunction() {
+/// endFunction - Gather and emit post-function exception information.
+void DwarfException::endFunction(const MachineFunction *) {
llvm_unreachable("Should be implemented");
}
diff --git a/lib/CodeGen/AsmPrinter/DwarfException.h b/lib/CodeGen/AsmPrinter/DwarfException.h
index 15751615b7..f792482751 100644
--- a/lib/CodeGen/AsmPrinter/DwarfException.h
+++ b/lib/CodeGen/AsmPrinter/DwarfException.h
@@ -14,6 +14,7 @@
#ifndef LLVM_CODEGEN_ASMPRINTER_DWARFEXCEPTION_H
#define LLVM_CODEGEN_ASMPRINTER_DWARFEXCEPTION_H
+#include "AsmPrinterHandler.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/CodeGen/AsmPrinter.h"
#include <vector>
@@ -35,7 +36,7 @@ class AsmPrinter;
//===----------------------------------------------------------------------===//
/// DwarfException - Emits Dwarf exception handling directives.
///
-class DwarfException {
+class DwarfException : public AsmPrinterHandler {
protected:
/// Asm - Target of Dwarf emission.
AsmPrinter *Asm;
@@ -47,9 +48,6 @@ protected:
static unsigned SharedTypeIds(const LandingPadInfo *L,
const LandingPadInfo *R);
- /// PadLT - Order landing pads lexicographically by type id.
- static bool PadLT(const LandingPadInfo *L, const LandingPadInfo *R);
-
/// PadRange - Structure holding a try-range and the associated landing pad.
struct PadRange {
// The index of the landing pad.
@@ -130,16 +128,21 @@ public:
DwarfException(AsmPrinter *A);
virtual ~DwarfException();
- /// EndModule - Emit all exception information that should come after the
+ /// endModule - Emit all exception information that should come after the
/// content.
- virtual void EndModule();
+ void endModule() override;
- /// BeginFunction - Gather pre-function exception information. Assumes being
+ /// beginFunction - Gather pre-function exception information. Assumes being
/// emitted immediately after the function entry point.
- virtual void BeginFunction(const MachineFunction *MF);
+ void beginFunction(const MachineFunction *MF) override;
+
+ /// endFunction - Gather and emit post-function exception information.
+ void endFunction(const MachineFunction *) override;
- /// EndFunction - Gather and emit post-function exception information.
- virtual void EndFunction();
+ // We don't need these.
+ void setSymbolSize(const MCSymbol *Sym, uint64_t Size) override {}
+ void beginInstruction(const MachineInstr *MI) override {}
+ void endInstruction() override {}
};
class DwarfCFIException : public DwarfException {
@@ -164,22 +167,26 @@ public:
DwarfCFIException(AsmPrinter *A);
virtual ~DwarfCFIException();
- /// EndModule - Emit all exception information that should come after the
+ /// endModule - Emit all exception information that should come after the
/// content.
- virtual void EndModule();
+ void endModule() override;
- /// BeginFunction - Gather pre-function exception information. Assumes being
+ /// beginFunction - Gather pre-function exception information. Assumes being
/// emitted immediately after the function entry point.
- virtual void BeginFunction(const MachineFunction *MF);
+ void beginFunction(const MachineFunction *MF) override;
- /// EndFunction - Gather and emit post-function exception information.
- virtual void EndFunction();
+ /// endFunction - Gather and emit post-function exception information.
+ void endFunction(const MachineFunction *) override;
};
class ARMException : public DwarfException {
- void EmitTypeInfos(unsigned TTypeEncoding);
+ void EmitTypeInfos(unsigned TTypeEncoding) override;
ARMTargetStreamer &getTargetStreamer();
+ /// shouldEmitCFI - Per-function flag to indicate if frame CFI info
+ /// should be emitted.
+ bool shouldEmitCFI;
+
public:
//===--------------------------------------------------------------------===//
// Main entry points.
@@ -187,16 +194,16 @@ public:
ARMException(AsmPrinter *A);
virtual ~ARMException();
- /// EndModule - Emit all exception information that should come after the
+ /// endModule - Emit all exception information that should come after the
/// content.
- virtual void EndModule();
+ void endModule() override;
- /// BeginFunction - Gather pre-function exception information. Assumes being
+ /// beginFunction - Gather pre-function exception information. Assumes being
/// emitted immediately after the function entry point.
- virtual void BeginFunction(const MachineFunction *MF);
+ void beginFunction(const MachineFunction *MF) override;
- /// EndFunction - Gather and emit post-function exception information.
- virtual void EndFunction();
+ /// endFunction - Gather and emit post-function exception information.
+ void endFunction(const MachineFunction *) override;
};
class Win64Exception : public DwarfException {
@@ -219,16 +226,16 @@ public:
Win64Exception(AsmPrinter *A);
virtual ~Win64Exception();
- /// EndModule - Emit all exception information that should come after the
+ /// endModule - Emit all exception information that should come after the
/// content.
- virtual void EndModule();
+ void endModule() override;
- /// BeginFunction - Gather pre-function exception information. Assumes being
+ /// beginFunction - Gather pre-function exception information. Assumes being
/// emitted immediately after the function entry point.
- virtual void BeginFunction(const MachineFunction *MF);
+ void beginFunction(const MachineFunction *MF) override;
- /// EndFunction - Gather and emit post-function exception information.
- virtual void EndFunction();
+ /// endFunction - Gather and emit post-function exception information.
+ void endFunction(const MachineFunction *) override;
};
} // End of namespace llvm
diff --git a/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp b/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
index a6ff953809..82e9bb008a 100644
--- a/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp
+++ b/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
@@ -1,4 +1,4 @@
-//===-- llvm/CodeGen/DwarfCompileUnit.cpp - Dwarf Compile Unit ------------===//
+//===-- llvm/CodeGen/DwarfUnit.cpp - Dwarf Type and Compile Units ---------===//
//
// The LLVM Compiler Infrastructure
//
@@ -13,50 +13,75 @@
#define DEBUG_TYPE "dwarfdebug"
-#include "DwarfCompileUnit.h"
+#include "DwarfUnit.h"
#include "DwarfAccelTable.h"
#include "DwarfDebug.h"
#include "llvm/ADT/APFloat.h"
-#include "llvm/DIBuilder.h"
#include "llvm/IR/Constants.h"
+#include "llvm/IR/DIBuilder.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/Instructions.h"
+#include "llvm/IR/Mangler.h"
+#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCSection.h"
#include "llvm/MC/MCStreamer.h"
-#include "llvm/Target/Mangler.h"
+#include "llvm/Support/CommandLine.h"
#include "llvm/Target/TargetFrameLowering.h"
-#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetLoweringObjectFile.h"
+#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetRegisterInfo.h"
using namespace llvm;
-/// CompileUnit - Compile unit constructor.
-CompileUnit::CompileUnit(unsigned UID, DIE *D, DICompileUnit Node,
- AsmPrinter *A, DwarfDebug *DW, DwarfUnits *DWU)
- : UniqueID(UID), Node(Node), CUDie(D), Asm(A), DD(DW), DU(DWU),
- IndexTyDie(0), DebugInfoOffset(0) {
+static cl::opt<bool>
+GenerateDwarfTypeUnits("generate-type-units", cl::Hidden,
+ cl::desc("Generate DWARF4 type units."),
+ cl::init(false));
+
+/// Unit - Unit constructor.
+DwarfUnit::DwarfUnit(unsigned UID, DIE *D, DICompileUnit Node, AsmPrinter *A,
+ DwarfDebug *DW, DwarfFile *DWU)
+ : UniqueID(UID), CUNode(Node), UnitDie(D), DebugInfoOffset(0), Asm(A),
+ DD(DW), DU(DWU), IndexTyDie(0), Section(0), Skeleton(0) {
DIEIntegerOne = new (DIEValueAllocator) DIEInteger(1);
+}
+
+DwarfCompileUnit::DwarfCompileUnit(unsigned UID, DIE *D, DICompileUnit Node,
+ AsmPrinter *A, DwarfDebug *DW,
+ DwarfFile *DWU)
+ : DwarfUnit(UID, D, Node, A, DW, DWU) {
insertDIE(Node, D);
}
-/// ~CompileUnit - Destructor for compile unit.
-CompileUnit::~CompileUnit() {
+DwarfTypeUnit::DwarfTypeUnit(unsigned UID, DIE *D, DwarfCompileUnit &CU,
+ AsmPrinter *A, DwarfDebug *DW, DwarfFile *DWU,
+ MCDwarfDwoLineTable *SplitLineTable)
+ : DwarfUnit(UID, D, CU.getCUNode(), A, DW, DWU), CU(CU),
+ SplitLineTable(SplitLineTable) {
+ if (SplitLineTable)
+ addSectionOffset(UnitDie.get(), dwarf::DW_AT_stmt_list, 0);
+}
+
+/// ~Unit - Destructor for compile unit.
+DwarfUnit::~DwarfUnit() {
for (unsigned j = 0, M = DIEBlocks.size(); j < M; ++j)
DIEBlocks[j]->~DIEBlock();
+ for (unsigned j = 0, M = DIELocs.size(); j < M; ++j)
+ DIELocs[j]->~DIELoc();
}
/// createDIEEntry - Creates a new DIEEntry to be a proxy for a debug
/// information entry.
-DIEEntry *CompileUnit::createDIEEntry(DIE *Entry) {
+DIEEntry *DwarfUnit::createDIEEntry(DIE *Entry) {
DIEEntry *Value = new (DIEValueAllocator) DIEEntry(Entry);
return Value;
}
/// getDefaultLowerBound - Return the default lower bound for an array. If the
/// DWARF version doesn't handle the language, return -1.
-int64_t CompileUnit::getDefaultLowerBound() const {
+int64_t DwarfUnit::getDefaultLowerBound() const {
switch (getLanguage()) {
default:
break;
@@ -100,17 +125,23 @@ int64_t CompileUnit::getDefaultLowerBound() const {
/// Check whether the DIE for this MDNode can be shared across CUs.
static bool isShareableAcrossCUs(DIDescriptor D) {
- // When the MDNode can be part of the type system, the DIE can be
- // shared across CUs.
- return D.isType() ||
- (D.isSubprogram() && !DISubprogram(D).isDefinition());
+ // When the MDNode can be part of the type system, the DIE can be shared
+ // across CUs.
+ // Combining type units and cross-CU DIE sharing is lower value (since
+ // cross-CU DIE sharing is used in LTO and removes type redundancy at that
+ // level already) but may be implementable for some value in projects
+ // building multiple independent libraries with LTO and then linking those
+ // together.
+ return (D.isType() ||
+ (D.isSubprogram() && !DISubprogram(D).isDefinition())) &&
+ !GenerateDwarfTypeUnits;
}
/// getDIE - Returns the debug information entry map slot for the
/// specified debug variable. We delegate the request to DwarfDebug
/// when the DIE for this MDNode can be shared across CUs. The mappings
/// will be kept in DwarfDebug for shareable DIEs.
-DIE *CompileUnit::getDIE(DIDescriptor D) const {
+DIE *DwarfUnit::getDIE(DIDescriptor D) const {
if (isShareableAcrossCUs(D))
return DD->getDIE(D);
return MDNodeToDieMap.lookup(D);
@@ -119,7 +150,7 @@ DIE *CompileUnit::getDIE(DIDescriptor D) const {
/// insertDIE - Insert DIE into the map. We delegate the request to DwarfDebug
/// when the DIE for this MDNode can be shared across CUs. The mappings
/// will be kept in DwarfDebug for shareable DIEs.
-void CompileUnit::insertDIE(DIDescriptor Desc, DIE *D) {
+void DwarfUnit::insertDIE(DIDescriptor Desc, DIE *D) {
if (isShareableAcrossCUs(Desc)) {
DD->insertDIE(Desc, D);
return;
@@ -128,7 +159,7 @@ void CompileUnit::insertDIE(DIDescriptor Desc, DIE *D) {
}
/// addFlag - Add a flag that is true.
-void CompileUnit::addFlag(DIE *Die, dwarf::Attribute Attribute) {
+void DwarfUnit::addFlag(DIE *Die, dwarf::Attribute Attribute) {
if (DD->getDwarfVersion() >= 4)
Die->addValue(Attribute, dwarf::DW_FORM_flag_present, DIEIntegerOne);
else
@@ -137,8 +168,8 @@ void CompileUnit::addFlag(DIE *Die, dwarf::Attribute Attribute) {
/// addUInt - Add an unsigned integer attribute data and value.
///
-void CompileUnit::addUInt(DIE *Die, dwarf::Attribute Attribute,
- Optional<dwarf::Form> Form, uint64_t Integer) {
+void DwarfUnit::addUInt(DIE *Die, dwarf::Attribute Attribute,
+ Optional<dwarf::Form> Form, uint64_t Integer) {
if (!Form)
Form = DIEInteger::BestForm(false, Integer);
DIEValue *Value = Integer == 1 ? DIEIntegerOne : new (DIEValueAllocator)
@@ -146,22 +177,22 @@ void CompileUnit::addUInt(DIE *Die, dwarf::Attribute Attribute,
Die->addValue(Attribute, *Form, Value);
}
-void CompileUnit::addUInt(DIEBlock *Block, dwarf::Form Form, uint64_t Integer) {
+void DwarfUnit::addUInt(DIE *Block, dwarf::Form Form, uint64_t Integer) {
addUInt(Block, (dwarf::Attribute)0, Form, Integer);
}
/// addSInt - Add an signed integer attribute data and value.
///
-void CompileUnit::addSInt(DIE *Die, dwarf::Attribute Attribute,
- Optional<dwarf::Form> Form, int64_t Integer) {
+void DwarfUnit::addSInt(DIE *Die, dwarf::Attribute Attribute,
+ Optional<dwarf::Form> Form, int64_t Integer) {
if (!Form)
Form = DIEInteger::BestForm(true, Integer);
DIEValue *Value = new (DIEValueAllocator) DIEInteger(Integer);
Die->addValue(Attribute, *Form, Value);
}
-void CompileUnit::addSInt(DIEBlock *Die, Optional<dwarf::Form> Form,
- int64_t Integer) {
+void DwarfUnit::addSInt(DIELoc *Die, Optional<dwarf::Form> Form,
+ int64_t Integer) {
addSInt(Die, (dwarf::Attribute)0, Form, Integer);
}
@@ -170,91 +201,135 @@ void CompileUnit::addSInt(DIEBlock *Die, Optional<dwarf::Form> Form,
/// more predictable sizes. In the case of split dwarf we emit an index
/// into another table which gets us the static offset into the string
/// table.
-void CompileUnit::addString(DIE *Die, dwarf::Attribute Attribute,
- StringRef String) {
- DIEValue *Value;
- dwarf::Form Form;
- if (!DD->useSplitDwarf()) {
- MCSymbol *Symb = DU->getStringPoolEntry(String);
- if (Asm->needsRelocationsForDwarfStringPool())
- Value = new (DIEValueAllocator) DIELabel(Symb);
- else {
- MCSymbol *StringPool = DU->getStringPoolSym();
- Value = new (DIEValueAllocator) DIEDelta(Symb, StringPool);
- }
- Form = dwarf::DW_FORM_strp;
- } else {
- unsigned idx = DU->getStringPoolIndex(String);
- Value = new (DIEValueAllocator) DIEInteger(idx);
- Form = dwarf::DW_FORM_GNU_str_index;
- }
+void DwarfUnit::addString(DIE *Die, dwarf::Attribute Attribute,
+ StringRef String) {
+
+ if (!DD->useSplitDwarf())
+ return addLocalString(Die, Attribute, String);
+
+ unsigned idx = DU->getStringPoolIndex(String);
+ DIEValue *Value = new (DIEValueAllocator) DIEInteger(idx);
DIEValue *Str = new (DIEValueAllocator) DIEString(Value, String);
- Die->addValue(Attribute, Form, Str);
+ Die->addValue(Attribute, dwarf::DW_FORM_GNU_str_index, Str);
}
/// addLocalString - Add a string attribute data and value. This is guaranteed
/// to be in the local string pool instead of indirected.
-void CompileUnit::addLocalString(DIE *Die, dwarf::Attribute Attribute,
- StringRef String) {
+void DwarfUnit::addLocalString(DIE *Die, dwarf::Attribute Attribute,
+ StringRef String) {
MCSymbol *Symb = DU->getStringPoolEntry(String);
DIEValue *Value;
- if (Asm->needsRelocationsForDwarfStringPool())
+ if (Asm->MAI->doesDwarfUseRelocationsAcrossSections())
Value = new (DIEValueAllocator) DIELabel(Symb);
else {
MCSymbol *StringPool = DU->getStringPoolSym();
Value = new (DIEValueAllocator) DIEDelta(Symb, StringPool);
}
- Die->addValue(Attribute, dwarf::DW_FORM_strp, Value);
+ DIEValue *Str = new (DIEValueAllocator) DIEString(Value, String);
+ Die->addValue(Attribute, dwarf::DW_FORM_strp, Str);
}
/// addExpr - Add a Dwarf expression attribute data and value.
///
-void CompileUnit::addExpr(DIEBlock *Die, dwarf::Form Form, const MCExpr *Expr) {
+void DwarfUnit::addExpr(DIELoc *Die, dwarf::Form Form, const MCExpr *Expr) {
DIEValue *Value = new (DIEValueAllocator) DIEExpr(Expr);
Die->addValue((dwarf::Attribute)0, Form, Value);
}
+/// addLocationList - Add a Dwarf loclistptr attribute data and value.
+///
+void DwarfUnit::addLocationList(DIE *Die, dwarf::Attribute Attribute,
+ unsigned Index) {
+ DIEValue *Value = new (DIEValueAllocator) DIELocList(Index);
+ dwarf::Form Form = DD->getDwarfVersion() >= 4 ? dwarf::DW_FORM_sec_offset
+ : dwarf::DW_FORM_data4;
+ Die->addValue(Attribute, Form, Value);
+}
+
/// addLabel - Add a Dwarf label attribute data and value.
///
-void CompileUnit::addLabel(DIE *Die, dwarf::Attribute Attribute,
- dwarf::Form Form, const MCSymbol *Label) {
+void DwarfUnit::addLabel(DIE *Die, dwarf::Attribute Attribute, dwarf::Form Form,
+ const MCSymbol *Label) {
DIEValue *Value = new (DIEValueAllocator) DIELabel(Label);
Die->addValue(Attribute, Form, Value);
}
-void CompileUnit::addLabel(DIEBlock *Die, dwarf::Form Form,
- const MCSymbol *Label) {
+void DwarfUnit::addLabel(DIELoc *Die, dwarf::Form Form, const MCSymbol *Label) {
addLabel(Die, (dwarf::Attribute)0, Form, Label);
}
+/// addSectionLabel - Add a Dwarf section label attribute data and value.
+///
+void DwarfUnit::addSectionLabel(DIE *Die, dwarf::Attribute Attribute,
+ const MCSymbol *Label) {
+ if (DD->getDwarfVersion() >= 4)
+ addLabel(Die, Attribute, dwarf::DW_FORM_sec_offset, Label);
+ else
+ addLabel(Die, Attribute, dwarf::DW_FORM_data4, Label);
+}
+
+/// addSectionOffset - Add an offset into a section attribute data and value.
+///
+void DwarfUnit::addSectionOffset(DIE *Die, dwarf::Attribute Attribute,
+ uint64_t Integer) {
+ if (DD->getDwarfVersion() >= 4)
+ addUInt(Die, Attribute, dwarf::DW_FORM_sec_offset, Integer);
+ else
+ addUInt(Die, Attribute, dwarf::DW_FORM_data4, Integer);
+}
+
/// addLabelAddress - Add a dwarf label attribute data and value using
/// DW_FORM_addr or DW_FORM_GNU_addr_index.
///
-void CompileUnit::addLabelAddress(DIE *Die, dwarf::Attribute Attribute,
- MCSymbol *Label) {
+void DwarfCompileUnit::addLabelAddress(DIE *Die, dwarf::Attribute Attribute,
+ const MCSymbol *Label) {
+
+ if (!DD->useSplitDwarf())
+ return addLocalLabelAddress(Die, Attribute, Label);
+
if (Label)
DD->addArangeLabel(SymbolCU(this, Label));
- if (!DD->useSplitDwarf()) {
- if (Label != NULL) {
- DIEValue *Value = new (DIEValueAllocator) DIELabel(Label);
- Die->addValue(Attribute, dwarf::DW_FORM_addr, Value);
- } else {
- DIEValue *Value = new (DIEValueAllocator) DIEInteger(0);
- Die->addValue(Attribute, dwarf::DW_FORM_addr, Value);
- }
+ unsigned idx = DU->getAddrPoolIndex(Label);
+ DIEValue *Value = new (DIEValueAllocator) DIEInteger(idx);
+ Die->addValue(Attribute, dwarf::DW_FORM_GNU_addr_index, Value);
+}
+
+void DwarfCompileUnit::addLocalLabelAddress(DIE *Die,
+ dwarf::Attribute Attribute,
+ const MCSymbol *Label) {
+ if (Label)
+ DD->addArangeLabel(SymbolCU(this, Label));
+
+ if (Label) {
+ DIEValue *Value = new (DIEValueAllocator) DIELabel(Label);
+ Die->addValue(Attribute, dwarf::DW_FORM_addr, Value);
} else {
- unsigned idx = DU->getAddrPoolIndex(Label);
- DIEValue *Value = new (DIEValueAllocator) DIEInteger(idx);
- Die->addValue(Attribute, dwarf::DW_FORM_GNU_addr_index, Value);
+ DIEValue *Value = new (DIEValueAllocator) DIEInteger(0);
+ Die->addValue(Attribute, dwarf::DW_FORM_addr, Value);
}
}
+unsigned DwarfCompileUnit::getOrCreateSourceID(StringRef FileName, StringRef DirName) {
+ // If we print assembly, we can't separate .file entries according to
+ // compile units. Thus all files will belong to the default compile unit.
+
+ // FIXME: add a better feature test than hasRawTextSupport. Even better,
+ // extend .file to support this.
+ return Asm->OutStreamer.EmitDwarfFileDirective(
+ 0, DirName, FileName,
+ Asm->OutStreamer.hasRawTextSupport() ? 0 : getUniqueID());
+}
+
+unsigned DwarfTypeUnit::getOrCreateSourceID(StringRef FileName, StringRef DirName) {
+ return SplitLineTable ? SplitLineTable->getFile(DirName, FileName)
+ : getCU().getOrCreateSourceID(FileName, DirName);
+}
+
/// addOpAddress - Add a dwarf op address data and value using the
/// form given and an op of either DW_FORM_addr or DW_FORM_GNU_addr_index.
///
-void CompileUnit::addOpAddress(DIEBlock *Die, const MCSymbol *Sym) {
- DD->addArangeLabel(SymbolCU(this, Sym));
+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);
@@ -264,31 +339,43 @@ void CompileUnit::addOpAddress(DIEBlock *Die, const MCSymbol *Sym) {
}
}
-/// addDelta - Add a label delta attribute data and value.
+/// addSectionDelta - Add a section label delta attribute data and value.
///
-void CompileUnit::addDelta(DIE *Die, dwarf::Attribute Attribute,
- dwarf::Form Form, const MCSymbol *Hi,
- const MCSymbol *Lo) {
+void DwarfUnit::addSectionDelta(DIE *Die, dwarf::Attribute Attribute,
+ const MCSymbol *Hi, const MCSymbol *Lo) {
DIEValue *Value = new (DIEValueAllocator) DIEDelta(Hi, Lo);
- Die->addValue(Attribute, Form, Value);
+ if (DD->getDwarfVersion() >= 4)
+ Die->addValue(Attribute, dwarf::DW_FORM_sec_offset, Value);
+ else
+ Die->addValue(Attribute, dwarf::DW_FORM_data4, Value);
+}
+
+void DwarfUnit::addLabelDelta(DIE *Die, dwarf::Attribute Attribute,
+ const MCSymbol *Hi, const MCSymbol *Lo) {
+ DIEValue *Value = new (DIEValueAllocator) DIEDelta(Hi, Lo);
+ Die->addValue(Attribute, dwarf::DW_FORM_data4, Value);
}
/// addDIEEntry - Add a DIE attribute data and value.
///
-void CompileUnit::addDIEEntry(DIE *Die, dwarf::Attribute Attribute,
- DIE *Entry) {
+void DwarfUnit::addDIEEntry(DIE *Die, dwarf::Attribute Attribute, DIE *Entry) {
addDIEEntry(Die, Attribute, createDIEEntry(Entry));
}
-void CompileUnit::addDIEEntry(DIE *Die, dwarf::Attribute Attribute,
- DIEEntry *Entry) {
- const DIE *DieCU = Die->getCompileUnitOrNull();
- const DIE *EntryCU = Entry->getEntry()->getCompileUnitOrNull();
+void DwarfUnit::addDIETypeSignature(DIE *Die, const DwarfTypeUnit &Type) {
+ Die->addValue(dwarf::DW_AT_signature, dwarf::DW_FORM_ref_sig8,
+ new (DIEValueAllocator) DIETypeSignature(Type));
+}
+
+void DwarfUnit::addDIEEntry(DIE *Die, dwarf::Attribute Attribute,
+ DIEEntry *Entry) {
+ const DIE *DieCU = Die->getUnitOrNull();
+ const DIE *EntryCU = Entry->getEntry()->getUnitOrNull();
if (!DieCU)
// We assume that Die belongs to this CU, if it is not linked to any CU yet.
- DieCU = getCUDie();
+ DieCU = getUnitDie();
if (!EntryCU)
- EntryCU = getCUDie();
+ EntryCU = getUnitDie();
Die->addValue(Attribute, EntryCU == DieCU ? dwarf::DW_FORM_ref4
: dwarf::DW_FORM_ref_addr,
Entry);
@@ -296,7 +383,7 @@ void CompileUnit::addDIEEntry(DIE *Die, dwarf::Attribute Attribute,
/// Create a DIE with the given Tag, add the DIE to its parent, and
/// call insertDIE if MD is not null.
-DIE *CompileUnit::createAndAddDIE(unsigned Tag, DIE &Parent, DIDescriptor N) {
+DIE *DwarfUnit::createAndAddDIE(unsigned Tag, DIE &Parent, DIDescriptor N) {
DIE *Die = new DIE(Tag);
Parent.addChild(Die);
if (N)
@@ -306,8 +393,14 @@ DIE *CompileUnit::createAndAddDIE(unsigned Tag, DIE &Parent, DIDescriptor N) {
/// addBlock - Add block data.
///
-void CompileUnit::addBlock(DIE *Die, dwarf::Attribute Attribute,
- DIEBlock *Block) {
+void DwarfUnit::addBlock(DIE *Die, dwarf::Attribute Attribute, DIELoc *Loc) {
+ Loc->ComputeSize(Asm);
+ DIELocs.push_back(Loc); // Memoize so we can call the destructor later on.
+ Die->addValue(Attribute, Loc->BestForm(DD->getDwarfVersion()), Loc);
+}
+
+void DwarfUnit::addBlock(DIE *Die, dwarf::Attribute Attribute,
+ DIEBlock *Block) {
Block->ComputeSize(Asm);
DIEBlocks.push_back(Block); // Memoize so we can call the destructor later on.
Die->addValue(Attribute, Block->BestForm(), Block);
@@ -315,17 +408,12 @@ void CompileUnit::addBlock(DIE *Die, dwarf::Attribute Attribute,
/// addSourceLine - Add location information to specified debug information
/// entry.
-void CompileUnit::addSourceLine(DIE *Die, DIVariable V) {
- // Verify variable.
- if (!V.isVariable())
- return;
-
- unsigned Line = V.getLineNumber();
+void DwarfUnit::addSourceLine(DIE *Die, unsigned Line, StringRef File,
+ StringRef Directory) {
if (Line == 0)
return;
- unsigned FileID =
- DD->getOrCreateSourceID(V.getContext().getFilename(),
- V.getContext().getDirectory(), getUniqueID());
+
+ unsigned FileID = getOrCreateSourceID(File, Directory);
assert(FileID && "Invalid file id");
addUInt(Die, dwarf::DW_AT_decl_file, None, FileID);
addUInt(Die, dwarf::DW_AT_decl_line, None, Line);
@@ -333,98 +421,59 @@ void CompileUnit::addSourceLine(DIE *Die, DIVariable V) {
/// addSourceLine - Add location information to specified debug information
/// entry.
-void CompileUnit::addSourceLine(DIE *Die, DIGlobalVariable G) {
- // Verify global variable.
- if (!G.isGlobalVariable())
- return;
+void DwarfUnit::addSourceLine(DIE *Die, DIVariable V) {
+ assert(V.isVariable());
- unsigned Line = G.getLineNumber();
- if (Line == 0)
- return;
- unsigned FileID =
- DD->getOrCreateSourceID(G.getFilename(), G.getDirectory(), getUniqueID());
- assert(FileID && "Invalid file id");
- addUInt(Die, dwarf::DW_AT_decl_file, None, FileID);
- addUInt(Die, dwarf::DW_AT_decl_line, None, Line);
+ addSourceLine(Die, V.getLineNumber(), V.getContext().getFilename(),
+ V.getContext().getDirectory());
}
/// addSourceLine - Add location information to specified debug information
/// entry.
-void CompileUnit::addSourceLine(DIE *Die, DISubprogram SP) {
- // Verify subprogram.
- if (!SP.isSubprogram())
- return;
+void DwarfUnit::addSourceLine(DIE *Die, DIGlobalVariable G) {
+ assert(G.isGlobalVariable());
- // If the line number is 0, don't add it.
- unsigned Line = SP.getLineNumber();
- if (Line == 0)
- return;
+ addSourceLine(Die, G.getLineNumber(), G.getFilename(), G.getDirectory());
+}
- unsigned FileID = DD->getOrCreateSourceID(SP.getFilename(), SP.getDirectory(),
- getUniqueID());
- assert(FileID && "Invalid file id");
- addUInt(Die, dwarf::DW_AT_decl_file, None, FileID);
- addUInt(Die, dwarf::DW_AT_decl_line, None, Line);
+/// addSourceLine - Add location information to specified debug information
+/// entry.
+void DwarfUnit::addSourceLine(DIE *Die, DISubprogram SP) {
+ assert(SP.isSubprogram());
+
+ addSourceLine(Die, SP.getLineNumber(), SP.getFilename(), SP.getDirectory());
}
/// addSourceLine - Add location information to specified debug information
/// entry.
-void CompileUnit::addSourceLine(DIE *Die, DIType Ty) {
- // Verify type.
- if (!Ty.isType())
- return;
+void DwarfUnit::addSourceLine(DIE *Die, DIType Ty) {
+ assert(Ty.isType());
- unsigned Line = Ty.getLineNumber();
- if (Line == 0)
- return;
- unsigned FileID = DD->getOrCreateSourceID(Ty.getFilename(), Ty.getDirectory(),
- getUniqueID());
- assert(FileID && "Invalid file id");
- addUInt(Die, dwarf::DW_AT_decl_file, None, FileID);
- addUInt(Die, dwarf::DW_AT_decl_line, None, Line);
+ addSourceLine(Die, Ty.getLineNumber(), Ty.getFilename(), Ty.getDirectory());
}
/// addSourceLine - Add location information to specified debug information
/// entry.
-void CompileUnit::addSourceLine(DIE *Die, DIObjCProperty Ty) {
- // Verify type.
- if (!Ty.isObjCProperty())
- return;
+void DwarfUnit::addSourceLine(DIE *Die, DIObjCProperty Ty) {
+ assert(Ty.isObjCProperty());
- unsigned Line = Ty.getLineNumber();
- if (Line == 0)
- return;
DIFile File = Ty.getFile();
- unsigned FileID = DD->getOrCreateSourceID(File.getFilename(),
- File.getDirectory(), getUniqueID());
- assert(FileID && "Invalid file id");
- addUInt(Die, dwarf::DW_AT_decl_file, None, FileID);
- addUInt(Die, dwarf::DW_AT_decl_line, None, Line);
+ addSourceLine(Die, Ty.getLineNumber(), File.getFilename(),
+ File.getDirectory());
}
/// addSourceLine - Add location information to specified debug information
/// entry.
-void CompileUnit::addSourceLine(DIE *Die, DINameSpace NS) {
- // Verify namespace.
- if (!NS.Verify())
- return;
-
- unsigned Line = NS.getLineNumber();
- if (Line == 0)
- return;
- StringRef FN = NS.getFilename();
+void DwarfUnit::addSourceLine(DIE *Die, DINameSpace NS) {
+ assert(NS.Verify());
- unsigned FileID =
- DD->getOrCreateSourceID(FN, NS.getDirectory(), getUniqueID());
- assert(FileID && "Invalid file id");
- addUInt(Die, dwarf::DW_AT_decl_file, None, FileID);
- addUInt(Die, dwarf::DW_AT_decl_line, None, Line);
+ addSourceLine(Die, NS.getLineNumber(), NS.getFilename(), NS.getDirectory());
}
/// addVariableAddress - Add DW_AT_location attribute for a
/// DbgVariable based on provided MachineLocation.
-void CompileUnit::addVariableAddress(const DbgVariable &DV, DIE *Die,
- MachineLocation Location) {
+void DwarfUnit::addVariableAddress(const DbgVariable &DV, DIE *Die,
+ MachineLocation Location) {
if (DV.variableHasComplexAddress())
addComplexAddress(DV, Die, dwarf::DW_AT_location, Location);
else if (DV.isBlockByrefVariable())
@@ -435,20 +484,53 @@ void CompileUnit::addVariableAddress(const DbgVariable &DV, DIE *Die,
}
/// addRegisterOp - Add register operand.
-void CompileUnit::addRegisterOp(DIEBlock *TheDie, unsigned Reg) {
+void DwarfUnit::addRegisterOp(DIELoc *TheDie, unsigned Reg) {
const TargetRegisterInfo *RI = Asm->TM.getRegisterInfo();
- unsigned DWReg = RI->getDwarfRegNum(Reg, false);
+ int DWReg = RI->getDwarfRegNum(Reg, false);
+ bool isSubRegister = DWReg < 0;
+
+ unsigned Idx = 0;
+
+ // Go up the super-register chain until we hit a valid dwarf register number.
+ for (MCSuperRegIterator SR(Reg, RI); SR.isValid() && DWReg < 0; ++SR) {
+ DWReg = RI->getDwarfRegNum(*SR, false);
+ if (DWReg >= 0)
+ Idx = RI->getSubRegIndex(*SR, Reg);
+ }
+
+ if (DWReg < 0) {
+ DEBUG(dbgs() << "Invalid Dwarf register number.\n");
+ addUInt(TheDie, dwarf::DW_FORM_data1, dwarf::DW_OP_nop);
+ return;
+ }
+
+ // Emit register
if (DWReg < 32)
addUInt(TheDie, dwarf::DW_FORM_data1, dwarf::DW_OP_reg0 + DWReg);
else {
addUInt(TheDie, dwarf::DW_FORM_data1, dwarf::DW_OP_regx);
addUInt(TheDie, dwarf::DW_FORM_udata, DWReg);
}
+
+ // Emit Mask
+ if (isSubRegister) {
+ unsigned Size = RI->getSubRegIdxSize(Idx);
+ unsigned Offset = RI->getSubRegIdxOffset(Idx);
+ if (Offset > 0) {
+ addUInt(TheDie, dwarf::DW_FORM_data1, dwarf::DW_OP_bit_piece);
+ addUInt(TheDie, dwarf::DW_FORM_data1, Size);
+ addUInt(TheDie, dwarf::DW_FORM_data1, Offset);
+ } else {
+ unsigned ByteSize = Size / 8; // Assuming 8 bits per byte.
+ addUInt(TheDie, dwarf::DW_FORM_data1, dwarf::DW_OP_piece);
+ addUInt(TheDie, dwarf::DW_FORM_data1, ByteSize);
+ }
+ }
}
/// addRegisterOffset - Add register offset.
-void CompileUnit::addRegisterOffset(DIEBlock *TheDie, unsigned Reg,
- int64_t Offset) {
+void DwarfUnit::addRegisterOffset(DIELoc *TheDie, unsigned Reg,
+ int64_t Offset) {
const TargetRegisterInfo *RI = Asm->TM.getRegisterInfo();
unsigned DWReg = RI->getDwarfRegNum(Reg, false);
const TargetRegisterInfo *TRI = Asm->TM.getRegisterInfo();
@@ -466,59 +548,59 @@ void CompileUnit::addRegisterOffset(DIEBlock *TheDie, unsigned Reg,
/// addAddress - Add an address attribute to a die based on the location
/// provided.
-void CompileUnit::addAddress(DIE *Die, dwarf::Attribute Attribute,
- const MachineLocation &Location, bool Indirect) {
- DIEBlock *Block = new (DIEValueAllocator) DIEBlock();
+void DwarfUnit::addAddress(DIE *Die, dwarf::Attribute Attribute,
+ const MachineLocation &Location, bool Indirect) {
+ DIELoc *Loc = new (DIEValueAllocator) DIELoc();
if (Location.isReg() && !Indirect)
- addRegisterOp(Block, Location.getReg());
+ addRegisterOp(Loc, Location.getReg());
else {
- addRegisterOffset(Block, Location.getReg(), Location.getOffset());
+ addRegisterOffset(Loc, Location.getReg(), Location.getOffset());
if (Indirect && !Location.isReg()) {
- addUInt(Block, dwarf::DW_FORM_data1, dwarf::DW_OP_deref);
+ addUInt(Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_deref);
}
}
// Now attach the location information to the DIE.
- addBlock(Die, Attribute, Block);
+ addBlock(Die, Attribute, Loc);
}
/// addComplexAddress - Start with the address based on the location provided,
/// and generate the DWARF information necessary to find the actual variable
-/// given the extra address information encoded in the DIVariable, starting from
-/// the starting location. Add the DWARF information to the die.
+/// given the extra address information encoded in the DbgVariable, starting
+/// from the starting location. Add the DWARF information to the die.
///
-void CompileUnit::addComplexAddress(const DbgVariable &DV, DIE *Die,
- dwarf::Attribute Attribute,
- const MachineLocation &Location) {
- DIEBlock *Block = new (DIEValueAllocator) DIEBlock();
+void DwarfUnit::addComplexAddress(const DbgVariable &DV, DIE *Die,
+ dwarf::Attribute Attribute,
+ const MachineLocation &Location) {
+ DIELoc *Loc = new (DIEValueAllocator) DIELoc();
unsigned N = DV.getNumAddrElements();
unsigned i = 0;
if (Location.isReg()) {
if (N >= 2 && DV.getAddrElement(0) == DIBuilder::OpPlus) {
// If first address element is OpPlus then emit
// DW_OP_breg + Offset instead of DW_OP_reg + Offset.
- addRegisterOffset(Block, Location.getReg(), DV.getAddrElement(1));
+ addRegisterOffset(Loc, Location.getReg(), DV.getAddrElement(1));
i = 2;
} else
- addRegisterOp(Block, Location.getReg());
+ addRegisterOp(Loc, Location.getReg());
} else
- addRegisterOffset(Block, Location.getReg(), Location.getOffset());
+ addRegisterOffset(Loc, Location.getReg(), Location.getOffset());
for (; i < N; ++i) {
uint64_t Element = DV.getAddrElement(i);
if (Element == DIBuilder::OpPlus) {
- addUInt(Block, dwarf::DW_FORM_data1, dwarf::DW_OP_plus_uconst);
- addUInt(Block, dwarf::DW_FORM_udata, DV.getAddrElement(++i));
+ addUInt(Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_plus_uconst);
+ addUInt(Loc, dwarf::DW_FORM_udata, DV.getAddrElement(++i));
} else if (Element == DIBuilder::OpDeref) {
if (!Location.isReg())
- addUInt(Block, dwarf::DW_FORM_data1, dwarf::DW_OP_deref);
+ addUInt(Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_deref);
} else
llvm_unreachable("unknown DIBuilder Opcode");
}
// Now attach the location information to the DIE.
- addBlock(Die, Attribute, Block);
+ addBlock(Die, Attribute, Loc);
}
/* Byref variables, in Blocks, are declared by the programmer as "SomeType
@@ -581,9 +663,9 @@ void CompileUnit::addComplexAddress(const DbgVariable &DV, DIE *Die,
/// starting location. Add the DWARF information to the die. For
/// more information, read large comment just above here.
///
-void CompileUnit::addBlockByrefAddress(const DbgVariable &DV, DIE *Die,
- dwarf::Attribute Attribute,
- const MachineLocation &Location) {
+void DwarfUnit::addBlockByrefAddress(const DbgVariable &DV, DIE *Die,
+ dwarf::Attribute Attribute,
+ const MachineLocation &Location) {
DIType Ty = DV.getType();
DIType TmpTy = Ty;
uint16_t Tag = Ty.getTag();
@@ -620,40 +702,40 @@ void CompileUnit::addBlockByrefAddress(const DbgVariable &DV, DIE *Die,
// Decode the original location, and use that as the start of the byref
// variable's location.
- DIEBlock *Block = new (DIEValueAllocator) DIEBlock();
+ DIELoc *Loc = new (DIEValueAllocator) DIELoc();
if (Location.isReg())
- addRegisterOp(Block, Location.getReg());
+ addRegisterOp(Loc, Location.getReg());
else
- addRegisterOffset(Block, Location.getReg(), Location.getOffset());
+ addRegisterOffset(Loc, Location.getReg(), Location.getOffset());
// 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)
- addUInt(Block, dwarf::DW_FORM_data1, dwarf::DW_OP_deref);
+ addUInt(Loc, dwarf::DW_FORM_data1, 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) {
- addUInt(Block, dwarf::DW_FORM_data1, dwarf::DW_OP_plus_uconst);
- addUInt(Block, dwarf::DW_FORM_udata, forwardingFieldOffset);
+ addUInt(Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_plus_uconst);
+ addUInt(Loc, dwarf::DW_FORM_udata, forwardingFieldOffset);
}
// Now dereference the __forwarding field to get to the real __Block_byref
// struct: DW_OP_deref.
- addUInt(Block, dwarf::DW_FORM_data1, dwarf::DW_OP_deref);
+ addUInt(Loc, dwarf::DW_FORM_data1, 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) {
- addUInt(Block, dwarf::DW_FORM_data1, dwarf::DW_OP_plus_uconst);
- addUInt(Block, dwarf::DW_FORM_udata, varFieldOffset);
+ addUInt(Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_plus_uconst);
+ addUInt(Loc, dwarf::DW_FORM_udata, varFieldOffset);
}
// Now attach the location information to the DIE.
- addBlock(Die, Attribute, Block);
+ addBlock(Die, Attribute, Loc);
}
/// isTypeSigned - Return true if the type is signed.
@@ -698,8 +780,9 @@ static uint64_t getBaseTypeSize(DwarfDebug *DD, DIDerivedType Ty) {
DIType BaseType = DD->resolve(Ty.getTypeDerivedFrom());
- // If this type is not derived from any type then take conservative approach.
- if (!BaseType.isValid())
+ // If this type is not derived from any type or the type is a declaration then
+ // take conservative approach.
+ if (!BaseType.isValid() || BaseType.isForwardDecl())
return Ty.getSizeInBits();
// If this is a derived type, go ahead and get the base type, unless it's a
@@ -716,8 +799,8 @@ static uint64_t getBaseTypeSize(DwarfDebug *DD, DIDerivedType Ty) {
}
/// addConstantValue - Add constant value entry in variable DIE.
-void CompileUnit::addConstantValue(DIE *Die, const MachineOperand &MO,
- DIType Ty) {
+void DwarfUnit::addConstantValue(DIE *Die, const MachineOperand &MO,
+ DIType Ty) {
// FIXME: This is a bit conservative/simple - it emits negative values at
// their maximum bit width which is a bit unfortunate (& doesn't prefer
// udata/sdata over dataN as suggested by the DWARF spec)
@@ -755,7 +838,7 @@ void CompileUnit::addConstantValue(DIE *Die, const MachineOperand &MO,
}
/// addConstantFPValue - Add constant value entry in variable DIE.
-void CompileUnit::addConstantFPValue(DIE *Die, const MachineOperand &MO) {
+void DwarfUnit::addConstantFPValue(DIE *Die, const MachineOperand &MO) {
assert(MO.isFPImm() && "Invalid machine operand!");
DIEBlock *Block = new (DIEValueAllocator) DIEBlock();
APFloat FPImm = MO.getFPImm()->getValueAPF();
@@ -778,19 +861,19 @@ void CompileUnit::addConstantFPValue(DIE *Die, const MachineOperand &MO) {
}
/// addConstantFPValue - Add constant value entry in variable DIE.
-void CompileUnit::addConstantFPValue(DIE *Die, const ConstantFP *CFP) {
+void DwarfUnit::addConstantFPValue(DIE *Die, const ConstantFP *CFP) {
// Pass this down to addConstantValue as an unsigned bag of bits.
addConstantValue(Die, CFP->getValueAPF().bitcastToAPInt(), true);
}
/// addConstantValue - Add constant value entry in variable DIE.
-void CompileUnit::addConstantValue(DIE *Die, const ConstantInt *CI,
- bool Unsigned) {
+void DwarfUnit::addConstantValue(DIE *Die, const ConstantInt *CI,
+ bool Unsigned) {
addConstantValue(Die, CI->getValue(), Unsigned);
}
// addConstantValue - Add constant value entry in variable DIE.
-void CompileUnit::addConstantValue(DIE *Die, const APInt &Val, bool Unsigned) {
+void DwarfUnit::addConstantValue(DIE *Die, const APInt &Val, bool Unsigned) {
unsigned CIBitWidth = Val.getBitWidth();
if (CIBitWidth <= 64) {
// If we're a signed constant definitely use sdata.
@@ -846,7 +929,7 @@ void CompileUnit::addConstantValue(DIE *Die, const APInt &Val, bool Unsigned) {
}
/// addTemplateParams - Add template parameters into buffer.
-void CompileUnit::addTemplateParams(DIE &Buffer, DIArray TParams) {
+void DwarfUnit::addTemplateParams(DIE &Buffer, DIArray TParams) {
// Add template parameters.
for (unsigned i = 0, e = TParams.getNumElements(); i != e; ++i) {
DIDescriptor Element = TParams.getElement(i);
@@ -860,9 +943,9 @@ void CompileUnit::addTemplateParams(DIE &Buffer, DIArray TParams) {
}
/// getOrCreateContextDIE - Get context owner's DIE.
-DIE *CompileUnit::getOrCreateContextDIE(DIScope Context) {
+DIE *DwarfUnit::getOrCreateContextDIE(DIScope Context) {
if (!Context || Context.isFile())
- return getCUDie();
+ return getUnitDie();
if (Context.isType())
return getOrCreateTypeDIE(DIType(Context));
if (Context.isNameSpace())
@@ -872,18 +955,38 @@ DIE *CompileUnit::getOrCreateContextDIE(DIScope Context) {
return getDIE(Context);
}
+DIE *DwarfUnit::createTypeDIE(DICompositeType Ty) {
+ DIScope Context = resolve(Ty.getContext());
+ DIE *ContextDIE = getOrCreateContextDIE(Context);
+
+ DIE *TyDIE = getDIE(Ty);
+ if (TyDIE)
+ return TyDIE;
+
+ // Create new type.
+ TyDIE = createAndAddDIE(Ty.getTag(), *ContextDIE, Ty);
+
+ constructTypeDIE(*TyDIE, Ty);
+
+ updateAcceleratorTables(Context, Ty, TyDIE);
+ return TyDIE;
+}
+
/// getOrCreateTypeDIE - Find existing DIE or create new DIE for the
/// given DIType.
-DIE *CompileUnit::getOrCreateTypeDIE(const MDNode *TyNode) {
+DIE *DwarfUnit::getOrCreateTypeDIE(const MDNode *TyNode) {
if (!TyNode)
return NULL;
DIType Ty(TyNode);
assert(Ty.isType());
+ assert(Ty == resolve(Ty.getRef()) &&
+ "type was not uniqued, possible ODR violation.");
// Construct the context before querying for the existence of the DIE in case
// such construction creates the DIE.
- DIE *ContextDIE = getOrCreateContextDIE(resolve(Ty.getContext()));
+ DIScope Context = resolve(Ty.getContext());
+ DIE *ContextDIE = getOrCreateContextDIE(Context);
assert(ContextDIE);
DIE *TyDIE = getDIE(Ty);
@@ -893,16 +996,29 @@ DIE *CompileUnit::getOrCreateTypeDIE(const MDNode *TyNode) {
// Create new type.
TyDIE = createAndAddDIE(Ty.getTag(), *ContextDIE, Ty);
+ updateAcceleratorTables(Context, Ty, TyDIE);
+
if (Ty.isBasicType())
constructTypeDIE(*TyDIE, DIBasicType(Ty));
- else if (Ty.isCompositeType())
- constructTypeDIE(*TyDIE, DICompositeType(Ty));
- else {
+ else if (Ty.isCompositeType()) {
+ DICompositeType CTy(Ty);
+ if (GenerateDwarfTypeUnits && !Ty.isForwardDecl())
+ if (MDString *TypeId = CTy.getIdentifier()) {
+ DD->addDwarfTypeUnitType(getCU(), TypeId->getString(), TyDIE, CTy);
+ // Skip updating the accelerator tables since this is not the full type.
+ return TyDIE;
+ }
+ constructTypeDIE(*TyDIE, CTy);
+ } else {
assert(Ty.isDerivedType() && "Unknown kind of DIType");
constructTypeDIE(*TyDIE, DIDerivedType(Ty));
}
- // If this is a named finished type then include it in the list of types
- // for the accelerator tables.
+
+ return TyDIE;
+}
+
+void DwarfUnit::updateAcceleratorTables(DIScope Context, DIType Ty,
+ const DIE *TyDIE) {
if (!Ty.getName().empty() && !Ty.isForwardDecl()) {
bool IsImplementation = 0;
if (Ty.isCompositeType()) {
@@ -913,13 +1029,16 @@ DIE *CompileUnit::getOrCreateTypeDIE(const MDNode *TyNode) {
}
unsigned Flags = IsImplementation ? dwarf::DW_FLAG_type_implementation : 0;
addAccelType(Ty.getName(), std::make_pair(TyDIE, Flags));
- }
- return TyDIE;
+ if ((!Context || Context.isCompileUnit() || Context.isFile() ||
+ Context.isNameSpace()) &&
+ getCUNode().getEmissionKind() != DIBuilder::LineTablesOnly)
+ GlobalTypes[getParentContextString(Context) + Ty.getName().str()] = TyDIE;
+ }
}
/// addType - Add a new type attribute to the specified entity.
-void CompileUnit::addType(DIE *Entity, DIType Ty, dwarf::Attribute Attribute) {
+void DwarfUnit::addType(DIE *Entity, DIType Ty, dwarf::Attribute Attribute) {
assert(Ty && "Trying to add a type that doesn't exist?");
// Check for pre-existence.
@@ -937,66 +1056,59 @@ void CompileUnit::addType(DIE *Entity, DIType Ty, dwarf::Attribute Attribute) {
Entry = createDIEEntry(Buffer);
insertDIEEntry(Ty, Entry);
addDIEEntry(Entity, Attribute, Entry);
-
- // If this is a complete composite type then include it in the
- // list of global types.
- addGlobalType(Ty);
}
// Accelerator table mutators - add each name along with its companion
// DIE to the proper table while ensuring that the name that we're going
// to reference is in the string table. We do this since the names we
// add may not only be identical to the names in the DIE.
-void CompileUnit::addAccelName(StringRef Name, DIE *Die) {
+void DwarfUnit::addAccelName(StringRef Name, const DIE *Die) {
+ if (!DD->useDwarfAccelTables())
+ return;
DU->getStringPoolEntry(Name);
- std::vector<DIE *> &DIEs = AccelNames[Name];
+ std::vector<const DIE *> &DIEs = AccelNames[Name];
DIEs.push_back(Die);
}
-void CompileUnit::addAccelObjC(StringRef Name, DIE *Die) {
+void DwarfUnit::addAccelObjC(StringRef Name, const DIE *Die) {
+ if (!DD->useDwarfAccelTables())
+ return;
DU->getStringPoolEntry(Name);
- std::vector<DIE *> &DIEs = AccelObjC[Name];
+ std::vector<const DIE *> &DIEs = AccelObjC[Name];
DIEs.push_back(Die);
}
-void CompileUnit::addAccelNamespace(StringRef Name, DIE *Die) {
+void DwarfUnit::addAccelNamespace(StringRef Name, const DIE *Die) {
+ if (!DD->useDwarfAccelTables())
+ return;
DU->getStringPoolEntry(Name);
- std::vector<DIE *> &DIEs = AccelNamespace[Name];
+ std::vector<const DIE *> &DIEs = AccelNamespace[Name];
DIEs.push_back(Die);
}
-void CompileUnit::addAccelType(StringRef Name, std::pair<DIE *, unsigned> Die) {
+void DwarfUnit::addAccelType(StringRef Name,
+ std::pair<const DIE *, unsigned> Die) {
+ if (!DD->useDwarfAccelTables())
+ return;
DU->getStringPoolEntry(Name);
- std::vector<std::pair<DIE *, unsigned> > &DIEs = AccelTypes[Name];
+ std::vector<std::pair<const DIE *, unsigned> > &DIEs = AccelTypes[Name];
DIEs.push_back(Die);
}
/// addGlobalName - Add a new global name to the compile unit.
-void CompileUnit::addGlobalName(StringRef Name, DIE *Die, DIScope Context) {
+void DwarfUnit::addGlobalName(StringRef Name, DIE *Die, DIScope Context) {
+ if (getCUNode().getEmissionKind() == DIBuilder::LineTablesOnly)
+ return;
std::string FullName = getParentContextString(Context) + Name.str();
GlobalNames[FullName] = Die;
}
-/// addGlobalType - Add a new global type to the compile unit.
-///
-void CompileUnit::addGlobalType(DIType Ty) {
- DIScope Context = resolve(Ty.getContext());
- if (!Ty.getName().empty() && !Ty.isForwardDecl() &&
- (!Context || Context.isCompileUnit() || Context.isFile() ||
- Context.isNameSpace()))
- if (DIEEntry *Entry = getDIEEntry(Ty)) {
- std::string FullName =
- getParentContextString(Context) + Ty.getName().str();
- GlobalTypes[FullName] = Entry->getEntry();
- }
-}
-
/// getParentContextString - Walks the metadata parent chain in a language
/// specific manner (using the compile unit language) and returns
/// it as a string. This is done at the metadata level because DIEs may
/// not currently have been added to the parent context and walking the
/// DIEs looking for names is more expensive than walking the metadata.
-std::string CompileUnit::getParentContextString(DIScope Context) const {
+std::string DwarfUnit::getParentContextString(DIScope Context) const {
if (!Context)
return "";
@@ -1031,24 +1143,8 @@ std::string CompileUnit::getParentContextString(DIScope Context) const {
return CS;
}
-/// addPubTypes - Add subprogram argument types for pubtypes section.
-void CompileUnit::addPubTypes(DISubprogram SP) {
- DICompositeType SPTy = SP.getType();
- uint16_t SPTag = SPTy.getTag();
- if (SPTag != dwarf::DW_TAG_subroutine_type)
- return;
-
- DIArray Args = SPTy.getTypeArray();
- for (unsigned i = 0, e = Args.getNumElements(); i != e; ++i) {
- DIType ATy(Args.getElement(i));
- if (!ATy.isType())
- continue;
- addGlobalType(ATy);
- }
-}
-
/// constructTypeDIE - Construct basic type die from DIBasicType.
-void CompileUnit::constructTypeDIE(DIE &Buffer, DIBasicType BTy) {
+void DwarfUnit::constructTypeDIE(DIE &Buffer, DIBasicType BTy) {
// Get core information.
StringRef Name = BTy.getName();
// Add name if not anonymous or intermediate type.
@@ -1067,7 +1163,7 @@ void CompileUnit::constructTypeDIE(DIE &Buffer, DIBasicType BTy) {
}
/// constructTypeDIE - Construct derived type die from DIDerivedType.
-void CompileUnit::constructTypeDIE(DIE &Buffer, DIDerivedType DTy) {
+void DwarfUnit::constructTypeDIE(DIE &Buffer, DIDerivedType DTy) {
// Get core information.
StringRef Name = DTy.getName();
uint64_t Size = DTy.getSizeInBits() >> 3;
@@ -1094,40 +1190,25 @@ void CompileUnit::constructTypeDIE(DIE &Buffer, DIDerivedType DTy) {
addSourceLine(&Buffer, DTy);
}
-/// Return true if the type is appropriately scoped to be contained inside
-/// its own type unit.
-static bool isTypeUnitScoped(DIType Ty, const DwarfDebug *DD) {
- DIScope Parent = DD->resolve(Ty.getContext());
- while (Parent) {
- // Don't generate a hash for anything scoped inside a function.
- if (Parent.isSubprogram())
- return false;
- Parent = DD->resolve(Parent.getContext());
- }
- return true;
-}
-
-/// Return true if the type should be split out into a type unit.
-static bool shouldCreateTypeUnit(DICompositeType CTy, const DwarfDebug *DD) {
- uint16_t Tag = CTy.getTag();
-
- switch (Tag) {
- case dwarf::DW_TAG_structure_type:
- case dwarf::DW_TAG_union_type:
- case dwarf::DW_TAG_enumeration_type:
- case dwarf::DW_TAG_class_type:
- // If this is a class, structure, union, or enumeration type
- // that is a definition (not a declaration), and not scoped
- // inside a function then separate this out as a type unit.
- return !CTy.isForwardDecl() && isTypeUnitScoped(CTy, DD);
- default:
- return false;
+/// constructSubprogramArguments - Construct function argument DIEs.
+void DwarfUnit::constructSubprogramArguments(DIE &Buffer, DIArray Args) {
+ for (unsigned i = 1, N = Args.getNumElements(); i < N; ++i) {
+ DIDescriptor Ty = Args.getElement(i);
+ if (Ty.isUnspecifiedParameter()) {
+ assert(i == N-1 && "Unspecified parameter must be the last argument");
+ createAndAddDIE(dwarf::DW_TAG_unspecified_parameters, Buffer);
+ } else {
+ DIE *Arg = createAndAddDIE(dwarf::DW_TAG_formal_parameter, Buffer);
+ addType(Arg, DIType(Ty));
+ if (DIType(Ty).isArtificial())
+ addFlag(Arg, dwarf::DW_AT_artificial);
+ }
}
}
/// constructTypeDIE - Construct type DIE from DICompositeType.
-void CompileUnit::constructTypeDIE(DIE &Buffer, DICompositeType CTy) {
- // Get core information.
+void DwarfUnit::constructTypeDIE(DIE &Buffer, DICompositeType CTy) {
+ // Add name if not anonymous or intermediate type.
StringRef Name = CTy.getName();
uint64_t Size = CTy.getSizeInBits() >> 3;
@@ -1148,19 +1229,12 @@ void CompileUnit::constructTypeDIE(DIE &Buffer, DICompositeType CTy) {
addType(&Buffer, RTy);
bool isPrototyped = true;
- // Add arguments.
- for (unsigned i = 1, N = Elements.getNumElements(); i < N; ++i) {
- DIDescriptor Ty = Elements.getElement(i);
- if (Ty.isUnspecifiedParameter()) {
- createAndAddDIE(dwarf::DW_TAG_unspecified_parameters, Buffer);
- isPrototyped = false;
- } else {
- DIE *Arg = createAndAddDIE(dwarf::DW_TAG_formal_parameter, Buffer);
- addType(Arg, DIType(Ty));
- if (DIType(Ty).isArtificial())
- addFlag(Arg, dwarf::DW_AT_artificial);
- }
- }
+ if (Elements.getNumElements() == 2 &&
+ Elements.getElement(1).isUnspecifiedParameter())
+ isPrototyped = false;
+
+ constructSubprogramArguments(Buffer, Elements);
+
// Add prototype flag if we're dealing with a C language and the
// function has been prototyped.
uint16_t Language = getLanguage();
@@ -1168,6 +1242,12 @@ void CompileUnit::constructTypeDIE(DIE &Buffer, DICompositeType CTy) {
(Language == dwarf::DW_LANG_C89 || Language == dwarf::DW_LANG_C99 ||
Language == dwarf::DW_LANG_ObjC))
addFlag(&Buffer, dwarf::DW_AT_prototyped);
+
+ if (CTy.isLValueReference())
+ addFlag(&Buffer, dwarf::DW_AT_reference);
+
+ if (CTy.isRValueReference())
+ addFlag(&Buffer, dwarf::DW_AT_rvalue_reference);
} break;
case dwarf::DW_TAG_structure_type:
case dwarf::DW_TAG_union_type:
@@ -1177,21 +1257,9 @@ void CompileUnit::constructTypeDIE(DIE &Buffer, DICompositeType CTy) {
for (unsigned i = 0, N = Elements.getNumElements(); i < N; ++i) {
DIDescriptor Element = Elements.getElement(i);
DIE *ElemDie = NULL;
- if (Element.isSubprogram()) {
- DISubprogram SP(Element);
- ElemDie = getOrCreateSubprogramDIE(SP);
- if (SP.isProtected())
- addUInt(ElemDie, dwarf::DW_AT_accessibility, dwarf::DW_FORM_data1,
- dwarf::DW_ACCESS_protected);
- else if (SP.isPrivate())
- addUInt(ElemDie, dwarf::DW_AT_accessibility, dwarf::DW_FORM_data1,
- dwarf::DW_ACCESS_private);
- else
- addUInt(ElemDie, dwarf::DW_AT_accessibility, dwarf::DW_FORM_data1,
- dwarf::DW_ACCESS_public);
- if (SP.isExplicit())
- addFlag(ElemDie, dwarf::DW_AT_explicit);
- } else if (Element.isDerivedType()) {
+ if (Element.isSubprogram())
+ ElemDie = getOrCreateSubprogramDIE(DISubprogram(Element));
+ else if (Element.isDerivedType()) {
DIDerivedType DDTy(Element);
if (DDTy.getTag() == dwarf::DW_TAG_friend) {
ElemDie = createAndAddDIE(dwarf::DW_TAG_friend, Buffer);
@@ -1207,7 +1275,8 @@ void CompileUnit::constructTypeDIE(DIE &Buffer, DICompositeType CTy) {
ElemDie = createAndAddDIE(Property.getTag(), Buffer);
StringRef PropertyName = Property.getObjCPropertyName();
addString(ElemDie, dwarf::DW_AT_APPLE_property_name, PropertyName);
- addType(ElemDie, Property.getType());
+ if (Property.getType())
+ addType(ElemDie, Property.getType());
addSourceLine(ElemDie, Property);
StringRef GetterName = Property.getObjCPropertyGetterName();
if (!GetterName.empty())
@@ -1293,17 +1362,12 @@ void CompileUnit::constructTypeDIE(DIE &Buffer, DICompositeType CTy) {
addUInt(&Buffer, dwarf::DW_AT_APPLE_runtime_class, dwarf::DW_FORM_data1,
RLang);
}
- // If this is a type applicable to a type unit it then add it to the
- // list of types we'll compute a hash for later.
- if (shouldCreateTypeUnit(CTy, DD))
- DD->addTypeUnitType(&Buffer);
}
/// constructTemplateTypeParameterDIE - Construct new DIE for the given
/// DITemplateTypeParameter.
-void
-CompileUnit::constructTemplateTypeParameterDIE(DIE &Buffer,
- DITemplateTypeParameter TP) {
+void DwarfUnit::constructTemplateTypeParameterDIE(DIE &Buffer,
+ DITemplateTypeParameter TP) {
DIE *ParamDIE =
createAndAddDIE(dwarf::DW_TAG_template_type_parameter, Buffer);
// Add the type if it exists, it could be void and therefore no type.
@@ -1316,8 +1380,8 @@ CompileUnit::constructTemplateTypeParameterDIE(DIE &Buffer,
/// constructTemplateValueParameterDIE - Construct new DIE for the given
/// DITemplateValueParameter.
void
-CompileUnit::constructTemplateValueParameterDIE(DIE &Buffer,
- DITemplateValueParameter VP) {
+DwarfUnit::constructTemplateValueParameterDIE(DIE &Buffer,
+ DITemplateValueParameter VP) {
DIE *ParamDIE = createAndAddDIE(VP.getTag(), Buffer);
// Add the type if there is one, template template and template parameter
@@ -1333,12 +1397,12 @@ CompileUnit::constructTemplateValueParameterDIE(DIE &Buffer,
else if (GlobalValue *GV = dyn_cast<GlobalValue>(Val)) {
// For declaration non-type template parameters (such as global values and
// functions)
- DIEBlock *Block = new (DIEValueAllocator) DIEBlock();
- addOpAddress(Block, Asm->getSymbol(GV));
+ DIELoc *Loc = new (DIEValueAllocator) DIELoc();
+ addOpAddress(Loc, Asm->getSymbol(GV));
// Emit DW_OP_stack_value to use the address as the immediate value of the
// parameter, rather than a pointer to it.
- addUInt(Block, dwarf::DW_FORM_data1, dwarf::DW_OP_stack_value);
- addBlock(ParamDIE, dwarf::DW_AT_location, Block);
+ addUInt(Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_stack_value);
+ addBlock(ParamDIE, dwarf::DW_AT_location, Loc);
} else if (VP.getTag() == dwarf::DW_TAG_GNU_template_template_param) {
assert(isa<MDString>(Val));
addString(ParamDIE, dwarf::DW_AT_GNU_template_name,
@@ -1352,7 +1416,7 @@ CompileUnit::constructTemplateValueParameterDIE(DIE &Buffer,
}
/// getOrCreateNameSpace - Create a DIE for DINameSpace.
-DIE *CompileUnit::getOrCreateNameSpace(DINameSpace NS) {
+DIE *DwarfUnit::getOrCreateNameSpace(DINameSpace NS) {
// Construct the context before querying for the existence of the DIE in case
// such construction creates the DIE.
DIE *ContextDIE = getOrCreateContextDIE(NS.getContext());
@@ -1373,11 +1437,16 @@ DIE *CompileUnit::getOrCreateNameSpace(DINameSpace NS) {
}
/// getOrCreateSubprogramDIE - Create new DIE using SP.
-DIE *CompileUnit::getOrCreateSubprogramDIE(DISubprogram SP) {
+DIE *DwarfUnit::getOrCreateSubprogramDIE(DISubprogram SP) {
// Construct the context before querying for the existence of the DIE in case
// such construction creates the DIE (as is the case for member function
// declarations).
- DIE *ContextDIE = getOrCreateContextDIE(resolve(SP.getContext()));
+ DIScope Context = resolve(SP.getContext());
+ DIE *ContextDIE = getOrCreateContextDIE(Context);
+
+ // Unique declarations based on the ODR, where applicable.
+ SP = DISubprogram(DD->resolve(SP.getRef()));
+ assert(SP.Verify());
DIE *SPDie = getDIE(SP);
if (SPDie)
@@ -1386,7 +1455,7 @@ DIE *CompileUnit::getOrCreateSubprogramDIE(DISubprogram SP) {
DISubprogram SPDecl = SP.getFunctionDeclaration();
if (SPDecl.isSubprogram())
// Add subprogram definitions to the CU die directly.
- ContextDIE = CUDie.get();
+ ContextDIE = UnitDie.get();
// DW_TAG_inlined_subroutine may refer to this DIE.
SPDie = createAndAddDIE(dwarf::DW_TAG_subprogram, *ContextDIE, SP);
@@ -1440,7 +1509,7 @@ DIE *CompileUnit::getOrCreateSubprogramDIE(DISubprogram SP) {
unsigned VK = SP.getVirtuality();
if (VK) {
addUInt(SPDie, dwarf::DW_AT_virtuality, dwarf::DW_FORM_data1, VK);
- DIEBlock *Block = getDIEBlock();
+ DIELoc *Block = getDIELoc();
addUInt(Block, dwarf::DW_FORM_data1, dwarf::DW_OP_constu);
addUInt(Block, dwarf::DW_FORM_udata, SP.getVirtualIndex());
addBlock(SPDie, dwarf::DW_AT_vtable_elem_location, Block);
@@ -1453,13 +1522,7 @@ DIE *CompileUnit::getOrCreateSubprogramDIE(DISubprogram SP) {
// Add arguments. Do not add arguments for subprogram definition. They will
// be handled while processing variables.
- for (unsigned i = 1, N = Args.getNumElements(); i < N; ++i) {
- DIE *Arg = createAndAddDIE(dwarf::DW_TAG_formal_parameter, *SPDie);
- DIType ATy(Args.getElement(i));
- addType(Arg, ATy);
- if (ATy.isArtificial())
- addFlag(Arg, dwarf::DW_AT_artificial);
- }
+ constructSubprogramArguments(*SPDie, Args);
}
if (SP.isArtificial())
@@ -1475,6 +1538,25 @@ DIE *CompileUnit::getOrCreateSubprogramDIE(DISubprogram SP) {
addUInt(SPDie, dwarf::DW_AT_APPLE_isa, dwarf::DW_FORM_flag, isa);
}
+ if (SP.isLValueReference())
+ addFlag(SPDie, dwarf::DW_AT_reference);
+
+ if (SP.isRValueReference())
+ addFlag(SPDie, dwarf::DW_AT_rvalue_reference);
+
+ if (SP.isProtected())
+ addUInt(SPDie, dwarf::DW_AT_accessibility, dwarf::DW_FORM_data1,
+ dwarf::DW_ACCESS_protected);
+ else if (SP.isPrivate())
+ addUInt(SPDie, dwarf::DW_AT_accessibility, dwarf::DW_FORM_data1,
+ dwarf::DW_ACCESS_private);
+ else
+ addUInt(SPDie, dwarf::DW_AT_accessibility, dwarf::DW_FORM_data1,
+ dwarf::DW_ACCESS_public);
+
+ if (SP.isExplicit())
+ addFlag(SPDie, dwarf::DW_AT_explicit);
+
return SPDie;
}
@@ -1506,17 +1588,15 @@ static const ConstantExpr *getMergedGlobalExpr(const Value *V) {
}
/// createGlobalVariableDIE - create global variable DIE.
-void CompileUnit::createGlobalVariableDIE(DIGlobalVariable GV) {
-
+void DwarfCompileUnit::createGlobalVariableDIE(DIGlobalVariable GV) {
// Check for pre-existence.
if (getDIE(GV))
return;
- if (!GV.isGlobalVariable())
- return;
+ assert(GV.isGlobalVariable());
DIScope GVContext = GV.getContext();
- DIType GTy = GV.getType();
+ DIType GTy = DD->resolve(GV.getType());
// If this is a static data member definition, some attributes belong
// to the declaration DIE.
@@ -1558,44 +1638,46 @@ void CompileUnit::createGlobalVariableDIE(DIGlobalVariable GV) {
bool isGlobalVariable = GV.getGlobal() != NULL;
if (isGlobalVariable) {
addToAccelTable = true;
- DIEBlock *Block = new (DIEValueAllocator) DIEBlock();
+ DIELoc *Loc = new (DIEValueAllocator) DIELoc();
const MCSymbol *Sym = Asm->getSymbol(GV.getGlobal());
if (GV.getGlobal()->isThreadLocal()) {
// FIXME: Make this work with -gsplit-dwarf.
unsigned PointerSize = Asm->getDataLayout().getPointerSize();
assert((PointerSize == 4 || PointerSize == 8) &&
"Add support for other sizes if necessary");
- const MCExpr *Expr =
- Asm->getObjFileLowering().getDebugThreadLocalSymbol(Sym);
// Based on GCC's support for TLS:
if (!DD->useSplitDwarf()) {
// 1) Start with a constNu of the appropriate pointer size
- addUInt(Block, dwarf::DW_FORM_data1,
+ addUInt(Loc, dwarf::DW_FORM_data1,
PointerSize == 4 ? dwarf::DW_OP_const4u : dwarf::DW_OP_const8u);
// 2) containing the (relocated) offset of the TLS variable
// within the module's TLS block.
- addExpr(Block, dwarf::DW_FORM_udata, Expr);
+ addExpr(Loc, dwarf::DW_FORM_udata,
+ Asm->getObjFileLowering().getDebugThreadLocalSymbol(Sym));
} else {
- addUInt(Block, dwarf::DW_FORM_data1, dwarf::DW_OP_GNU_const_index);
- addUInt(Block, dwarf::DW_FORM_udata, DU->getAddrPoolIndex(Expr));
+ addUInt(Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_GNU_const_index);
+ addUInt(Loc, dwarf::DW_FORM_udata,
+ DU->getAddrPoolIndex(Sym, /* TLS */ true));
}
// 3) followed by a custom OP to make the debugger do a TLS lookup.
- addUInt(Block, dwarf::DW_FORM_data1, dwarf::DW_OP_GNU_push_tls_address);
- } else
- addOpAddress(Block, Sym);
+ addUInt(Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_GNU_push_tls_address);
+ } else {
+ DD->addArangeLabel(SymbolCU(this, Sym));
+ addOpAddress(Loc, Sym);
+ }
// Do not create specification DIE if context is either compile unit
// or a subprogram.
if (GVContext && GV.isDefinition() && !GVContext.isCompileUnit() &&
!GVContext.isFile() && !DD->isSubprogramContext(GVContext)) {
// Create specification DIE.
- VariableSpecDIE = createAndAddDIE(dwarf::DW_TAG_variable, *CUDie);
+ VariableSpecDIE = createAndAddDIE(dwarf::DW_TAG_variable, *UnitDie);
addDIEEntry(VariableSpecDIE, dwarf::DW_AT_specification, VariableDIE);
- addBlock(VariableSpecDIE, dwarf::DW_AT_location, Block);
+ addBlock(VariableSpecDIE, dwarf::DW_AT_location, Loc);
// A static member's declaration is already flagged as such.
if (!SDMDecl.Verify())
addFlag(VariableDIE, dwarf::DW_AT_declaration);
} else {
- addBlock(VariableDIE, dwarf::DW_AT_location, Block);
+ addBlock(VariableDIE, dwarf::DW_AT_location, Loc);
}
// Add the linkage name.
StringRef LinkageName = GV.getLinkageName();
@@ -1605,7 +1687,8 @@ void CompileUnit::createGlobalVariableDIE(DIGlobalVariable GV) {
// TAG_variable.
addString(IsStaticMember && VariableSpecDIE ? VariableSpecDIE
: VariableDIE,
- dwarf::DW_AT_MIPS_linkage_name,
+ DD->getDwarfVersion() >= 4 ? dwarf::DW_AT_linkage_name
+ : dwarf::DW_AT_MIPS_linkage_name,
GlobalValue::getRealLinkageName(LinkageName));
} else if (const ConstantInt *CI =
dyn_cast_or_null<ConstantInt>(GV.getConstant())) {
@@ -1617,15 +1700,17 @@ void CompileUnit::createGlobalVariableDIE(DIGlobalVariable GV) {
} else if (const ConstantExpr *CE = getMergedGlobalExpr(GV->getOperand(11))) {
addToAccelTable = true;
// GV is a merged global.
- DIEBlock *Block = new (DIEValueAllocator) DIEBlock();
+ DIELoc *Loc = new (DIEValueAllocator) DIELoc();
Value *Ptr = CE->getOperand(0);
- addOpAddress(Block, Asm->getSymbol(cast<GlobalValue>(Ptr)));
- addUInt(Block, dwarf::DW_FORM_data1, dwarf::DW_OP_constu);
+ MCSymbol *Sym = Asm->getSymbol(cast<GlobalValue>(Ptr));
+ DD->addArangeLabel(SymbolCU(this, Sym));
+ addOpAddress(Loc, Sym);
+ addUInt(Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_constu);
SmallVector<Value *, 3> Idx(CE->op_begin() + 1, CE->op_end());
- addUInt(Block, dwarf::DW_FORM_udata,
+ addUInt(Loc, dwarf::DW_FORM_udata,
Asm->getDataLayout().getIndexedOffset(Ptr->getType(), Idx));
- addUInt(Block, dwarf::DW_FORM_data1, dwarf::DW_OP_plus);
- addBlock(VariableDIE, dwarf::DW_AT_location, Block);
+ addUInt(Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_plus);
+ addBlock(VariableDIE, dwarf::DW_AT_location, Loc);
}
if (addToAccelTable) {
@@ -1644,8 +1729,7 @@ void CompileUnit::createGlobalVariableDIE(DIGlobalVariable GV) {
}
/// constructSubrangeDIE - Construct subrange DIE from DISubrange.
-void CompileUnit::constructSubrangeDIE(DIE &Buffer, DISubrange SR,
- DIE *IndexTy) {
+void DwarfUnit::constructSubrangeDIE(DIE &Buffer, DISubrange SR, DIE *IndexTy) {
DIE *DW_Subrange = createAndAddDIE(dwarf::DW_TAG_subrange_type, Buffer);
addDIEEntry(DW_Subrange, dwarf::DW_AT_type, IndexTy);
@@ -1670,7 +1754,7 @@ void CompileUnit::constructSubrangeDIE(DIE &Buffer, DISubrange SR,
}
/// constructArrayTypeDIE - Construct array type DIE from DICompositeType.
-void CompileUnit::constructArrayTypeDIE(DIE &Buffer, DICompositeType CTy) {
+void DwarfUnit::constructArrayTypeDIE(DIE &Buffer, DICompositeType CTy) {
if (CTy.isVector())
addFlag(&Buffer, dwarf::DW_AT_GNU_vector);
@@ -1682,12 +1766,12 @@ void CompileUnit::constructArrayTypeDIE(DIE &Buffer, DICompositeType CTy) {
// as different languages may have different sizes for indexes.
DIE *IdxTy = getIndexTyDie();
if (!IdxTy) {
- // Construct an anonymous type for index type.
- IdxTy = createAndAddDIE(dwarf::DW_TAG_base_type, *CUDie.get());
- addString(IdxTy, dwarf::DW_AT_name, "int");
- addUInt(IdxTy, dwarf::DW_AT_byte_size, None, sizeof(int32_t));
+ // Construct an integer type to use for indexes.
+ IdxTy = createAndAddDIE(dwarf::DW_TAG_base_type, *UnitDie);
+ addString(IdxTy, dwarf::DW_AT_name, "sizetype");
+ addUInt(IdxTy, dwarf::DW_AT_byte_size, None, sizeof(int64_t));
addUInt(IdxTy, dwarf::DW_AT_encoding, dwarf::DW_FORM_data1,
- dwarf::DW_ATE_signed);
+ dwarf::DW_ATE_unsigned);
setIndexTyDie(IdxTy);
}
@@ -1701,7 +1785,7 @@ void CompileUnit::constructArrayTypeDIE(DIE &Buffer, DICompositeType CTy) {
}
/// constructEnumTypeDIE - Construct an enum type DIE from DICompositeType.
-void CompileUnit::constructEnumTypeDIE(DIE &Buffer, DICompositeType CTy) {
+void DwarfUnit::constructEnumTypeDIE(DIE &Buffer, DICompositeType CTy) {
DIArray Elements = CTy.getTypeArray();
// Add enumerators to enumeration type.
@@ -1712,7 +1796,8 @@ void CompileUnit::constructEnumTypeDIE(DIE &Buffer, DICompositeType CTy) {
StringRef Name = Enum.getName();
addString(Enumerator, dwarf::DW_AT_name, Name);
int64_t Value = Enum.getEnumValue();
- addSInt(Enumerator, dwarf::DW_AT_const_value, dwarf::DW_FORM_sdata, Value);
+ addSInt(Enumerator, dwarf::DW_AT_const_value, dwarf::DW_FORM_sdata,
+ Value);
}
}
DIType DTy = resolve(CTy.getTypeDerivedFrom());
@@ -1724,7 +1809,7 @@ void CompileUnit::constructEnumTypeDIE(DIE &Buffer, DICompositeType CTy) {
/// constructContainingTypeDIEs - Construct DIEs for types that contain
/// vtables.
-void CompileUnit::constructContainingTypeDIEs() {
+void DwarfUnit::constructContainingTypeDIEs() {
for (DenseMap<DIE *, const MDNode *>::iterator CI = ContainingTypeMap.begin(),
CE = ContainingTypeMap.end();
CI != CE; ++CI) {
@@ -1740,7 +1825,7 @@ void CompileUnit::constructContainingTypeDIEs() {
}
/// constructVariableDIE - Construct a DIE for the given DbgVariable.
-DIE *CompileUnit::constructVariableDIE(DbgVariable &DV, bool isScopeAbstract) {
+DIE *DwarfUnit::constructVariableDIE(DbgVariable &DV, bool isScopeAbstract) {
StringRef Name = DV.getName();
// Define variable debug information entry.
@@ -1768,10 +1853,7 @@ DIE *CompileUnit::constructVariableDIE(DbgVariable &DV, bool isScopeAbstract) {
unsigned Offset = DV.getDotDebugLocOffset();
if (Offset != ~0U) {
- addLabel(VariableDie, dwarf::DW_AT_location,
- DD->getDwarfVersion() >= 4 ? dwarf::DW_FORM_sec_offset
- : dwarf::DW_FORM_data4,
- Asm->GetTempSymbol("debug_loc", Offset));
+ addLocationList(VariableDie, dwarf::DW_AT_location, Offset);
DV.setDIE(VariableDie);
return VariableDie;
}
@@ -1815,7 +1897,7 @@ DIE *CompileUnit::constructVariableDIE(DbgVariable &DV, bool isScopeAbstract) {
}
/// constructMemberDIE - Construct member DIE from DIDerivedType.
-void CompileUnit::constructMemberDIE(DIE &Buffer, DIDerivedType DT) {
+void DwarfUnit::constructMemberDIE(DIE &Buffer, DIDerivedType DT) {
DIE *MemberDie = createAndAddDIE(DT.getTag(), Buffer);
StringRef Name = DT.getName();
if (!Name.empty())
@@ -1825,16 +1907,13 @@ void CompileUnit::constructMemberDIE(DIE &Buffer, DIDerivedType DT) {
addSourceLine(MemberDie, DT);
- DIEBlock *MemLocationDie = new (DIEValueAllocator) DIEBlock();
- addUInt(MemLocationDie, dwarf::DW_FORM_data1, dwarf::DW_OP_plus_uconst);
-
if (DT.getTag() == dwarf::DW_TAG_inheritance && DT.isVirtual()) {
// For C++, virtual base classes are not at fixed offset. Use following
// expression to extract appropriate offset from vtable.
// BaseAddr = ObAddr + *((*ObAddr) - Offset)
- DIEBlock *VBaseLocationDie = new (DIEValueAllocator) DIEBlock();
+ DIELoc *VBaseLocationDie = new (DIEValueAllocator) DIELoc();
addUInt(VBaseLocationDie, dwarf::DW_FORM_data1, dwarf::DW_OP_dup);
addUInt(VBaseLocationDie, dwarf::DW_FORM_data1, dwarf::DW_OP_deref);
addUInt(VBaseLocationDie, dwarf::DW_FORM_data1, dwarf::DW_OP_constu);
@@ -1850,10 +1929,9 @@ void CompileUnit::constructMemberDIE(DIE &Buffer, DIDerivedType DT) {
uint64_t OffsetInBytes;
if (Size != FieldSize) {
- // Handle bitfield.
- addUInt(MemberDie, dwarf::DW_AT_byte_size, None,
- getBaseTypeSize(DD, DT) >> 3);
- addUInt(MemberDie, dwarf::DW_AT_bit_size, None, DT.getSizeInBits());
+ // Handle bitfield, assume bytes are 8 bits.
+ addUInt(MemberDie, dwarf::DW_AT_byte_size, None, FieldSize/8);
+ addUInt(MemberDie, dwarf::DW_AT_bit_size, None, Size);
uint64_t Offset = DT.getOffsetInBits();
uint64_t AlignMask = ~(DT.getAlignInBits() - 1);
@@ -1866,13 +1944,21 @@ void CompileUnit::constructMemberDIE(DIE &Buffer, DIDerivedType DT) {
Offset = FieldSize - (Offset + Size);
addUInt(MemberDie, dwarf::DW_AT_bit_offset, None, Offset);
- // Here WD_AT_data_member_location points to the anonymous
+ // Here DW_AT_data_member_location points to the anonymous
// field that includes this bit field.
OffsetInBytes = FieldOffset >> 3;
} else
// This is not a bitfield.
OffsetInBytes = DT.getOffsetInBits() >> 3;
- addUInt(MemberDie, dwarf::DW_AT_data_member_location, None, OffsetInBytes);
+
+ if (DD->getDwarfVersion() <= 2) {
+ DIELoc *MemLocationDie = new (DIEValueAllocator) DIELoc();
+ addUInt(MemLocationDie, dwarf::DW_FORM_data1, dwarf::DW_OP_plus_uconst);
+ addUInt(MemLocationDie, dwarf::DW_FORM_udata, OffsetInBytes);
+ addBlock(MemberDie, dwarf::DW_AT_data_member_location, MemLocationDie);
+ } else
+ addUInt(MemberDie, dwarf::DW_AT_data_member_location, None,
+ OffsetInBytes);
}
if (DT.isProtected())
@@ -1900,7 +1986,7 @@ void CompileUnit::constructMemberDIE(DIE &Buffer, DIDerivedType DT) {
}
/// getOrCreateStaticMemberDIE - Create new DIE for C++ static member.
-DIE *CompileUnit::getOrCreateStaticMemberDIE(DIDerivedType DT) {
+DIE *DwarfUnit::getOrCreateStaticMemberDIE(DIDerivedType DT) {
if (!DT.Verify())
return NULL;
@@ -1944,13 +2030,89 @@ DIE *CompileUnit::getOrCreateStaticMemberDIE(DIDerivedType DT) {
return StaticMemberDIE;
}
-void CompileUnit::emitHeader(const MCSection *ASection,
- const MCSymbol *ASectionSym) {
+void DwarfUnit::emitHeader(const MCSymbol *ASectionSym) const {
Asm->OutStreamer.AddComment("DWARF version number");
Asm->EmitInt16(DD->getDwarfVersion());
Asm->OutStreamer.AddComment("Offset Into Abbrev. Section");
- Asm->EmitSectionOffset(Asm->GetTempSymbol(ASection->getLabelBeginName()),
- ASectionSym);
+ // We share one abbreviations table across all units so it's always at the
+ // start of the section. Use a relocatable offset where needed to ensure
+ // linking doesn't invalidate that offset.
+ if (ASectionSym)
+ Asm->EmitSectionOffset(ASectionSym, ASectionSym);
+ else
+ // Use a constant value when no symbol is provided.
+ Asm->EmitInt32(0);
Asm->OutStreamer.AddComment("Address Size (in bytes)");
Asm->EmitInt8(Asm->getDataLayout().getPointerSize());
}
+
+void DwarfUnit::addRange(RangeSpan Range) {
+ // Only add a range for this unit if we're emitting full debug.
+ if (getCUNode().getEmissionKind() == DIBuilder::FullDebug) {
+ // If we have no current ranges just add the range and return, otherwise,
+ // check the current section and CU against the previous section and CU we
+ // emitted into and the subprogram was contained within. If these are the
+ // same then extend our current range, otherwise add this as a new range.
+ if (CURanges.size() == 0 ||
+ this != DD->getPrevCU() ||
+ Asm->getCurrentSection() != DD->getPrevSection()) {
+ CURanges.push_back(Range);
+ return;
+ }
+
+ assert(&(CURanges.back().getEnd()->getSection()) ==
+ &(Range.getEnd()->getSection()) &&
+ "We can only append to a range in the same section!");
+ CURanges.back().setEnd(Range.getEnd());
+ }
+}
+
+void DwarfCompileUnit::initStmtList(MCSymbol *DwarfLineSectionSym) {
+ // Define start line table label for each Compile Unit.
+ MCSymbol *LineTableStartSym =
+ Asm->OutStreamer.getDwarfLineTableSymbol(getUniqueID());
+
+ stmtListIndex = UnitDie->getValues().size();
+
+ // DW_AT_stmt_list is a offset of line number information for this
+ // compile unit in debug_line section. For split dwarf this is
+ // left in the skeleton CU and so not included.
+ // The line table entries are not always emitted in assembly, so it
+ // is not okay to use line_table_start here.
+ if (Asm->MAI->doesDwarfUseRelocationsAcrossSections())
+ addSectionLabel(UnitDie.get(), dwarf::DW_AT_stmt_list, LineTableStartSym);
+ else
+ addSectionDelta(UnitDie.get(), dwarf::DW_AT_stmt_list, LineTableStartSym,
+ DwarfLineSectionSym);
+}
+
+void DwarfCompileUnit::applyStmtList(DIE &D) {
+ D.addValue(dwarf::DW_AT_stmt_list,
+ UnitDie->getAbbrev().getData()[stmtListIndex].getForm(),
+ UnitDie->getValues()[stmtListIndex]);
+}
+
+void DwarfTypeUnit::emitHeader(const MCSymbol *ASectionSym) const {
+ DwarfUnit::emitHeader(ASectionSym);
+ Asm->OutStreamer.AddComment("Type Signature");
+ Asm->OutStreamer.EmitIntValue(TypeSignature, sizeof(TypeSignature));
+ Asm->OutStreamer.AddComment("Type DIE Offset");
+ // In a skeleton type unit there is no type DIE so emit a zero offset.
+ Asm->OutStreamer.EmitIntValue(Ty ? Ty->getOffset() : 0,
+ sizeof(Ty->getOffset()));
+}
+
+void DwarfTypeUnit::initSection(const MCSection *Section) {
+ assert(!this->Section);
+ this->Section = Section;
+ // Since each type unit is contained in its own COMDAT section, the begin
+ // label and the section label are the same. Using the begin label emission in
+ // DwarfDebug to emit the section label as well is slightly subtle/sneaky, but
+ // the only other alternative of lazily constructing start-of-section labels
+ // and storing a mapping in DwarfDebug (or AsmPrinter).
+ this->SectionSym = this->LabelBegin =
+ Asm->GetTempSymbol(Section->getLabelBeginName(), getUniqueID());
+ this->LabelEnd =
+ Asm->GetTempSymbol(Section->getLabelEndName(), getUniqueID());
+ this->LabelRange = Asm->GetTempSymbol("gnu_ranges", getUniqueID());
+}
diff --git a/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h b/lib/CodeGen/AsmPrinter/DwarfUnit.h
index d782c88a51..ef713f7cf0 100644
--- a/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h
+++ b/lib/CodeGen/AsmPrinter/DwarfUnit.h
@@ -1,4 +1,4 @@
-//===-- llvm/CodeGen/DwarfCompileUnit.h - Dwarf Compile Unit ---*- C++ -*--===//
+//===-- llvm/CodeGen/DwarfUnit.h - Dwarf Compile Unit ---*- C++ -*--===//
//
// The LLVM Compiler Infrastructure
//
@@ -18,10 +18,13 @@
#include "DwarfDebug.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/Optional.h"
-#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/StringMap.h"
-#include "llvm/DebugInfo.h"
+#include "llvm/CodeGen/AsmPrinter.h"
+#include "llvm/IR/DIBuilder.h"
+#include "llvm/IR/DebugInfo.h"
#include "llvm/MC/MCExpr.h"
+#include "llvm/MC/MCSection.h"
+#include "llvm/MC/MCDwarf.h"
namespace llvm {
@@ -30,30 +33,59 @@ class MachineOperand;
class ConstantInt;
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) : RangeSym(Sym) {}
+ MCSymbol *getSym() const { return RangeSym; }
+ const SmallVectorImpl<RangeSpan> &getRanges() const { return Ranges; }
+ void addRange(RangeSpan Range) { Ranges.push_back(Range); }
+};
//===----------------------------------------------------------------------===//
-/// CompileUnit - This dwarf writer support class manages information associated
+/// Unit - This dwarf writer support class manages information associated
/// with a source file.
-class CompileUnit {
+class DwarfUnit {
+protected:
/// UniqueID - a numeric ID unique among all CUs in the module
- ///
unsigned UniqueID;
/// Node - MDNode for the compile unit.
- DICompileUnit Node;
+ DICompileUnit CUNode;
- /// CUDie - Compile unit debug information entry.
- ///
- const OwningPtr<DIE> CUDie;
+ /// Unit debug information entry.
+ const std::unique_ptr<DIE> UnitDie;
+
+ /// Offset of the UnitDie from beginning of debug info section.
+ unsigned DebugInfoOffset;
/// Asm - Target of Dwarf emission.
AsmPrinter *Asm;
// Holders for some common dwarf information.
DwarfDebug *DD;
- DwarfUnits *DU;
+ DwarfFile *DU;
- /// IndexTyDie - An anonymous type for index type. Owned by CUDie.
+ /// IndexTyDie - An anonymous type for index type. Owned by UnitDie.
DIE *IndexTyDie;
/// MDNodeToDieMap - Tracks the mapping of unit level debug information
@@ -65,57 +97,150 @@ class CompileUnit {
DenseMap<const MDNode *, DIEEntry *> MDNodeToDIEEntryMap;
/// GlobalNames - A map of globally visible named entities for this unit.
- ///
- StringMap<DIE *> GlobalNames;
+ StringMap<const DIE *> GlobalNames;
/// GlobalTypes - A map of globally visible types for this unit.
- ///
- StringMap<DIE *> GlobalTypes;
+ StringMap<const DIE *> GlobalTypes;
/// AccelNames - A map of names for the name accelerator table.
- ///
- StringMap<std::vector<DIE *> > AccelNames;
- StringMap<std::vector<DIE *> > AccelObjC;
- StringMap<std::vector<DIE *> > AccelNamespace;
- StringMap<std::vector<std::pair<DIE *, unsigned> > > AccelTypes;
+ StringMap<std::vector<const DIE *> > AccelNames;
+
+ /// AccelObjC - A map of objc spec for the objc accelerator table.
+ StringMap<std::vector<const DIE *> > AccelObjC;
+
+ /// AccelNamespace - A map of names for the namespace accelerator table.
+ StringMap<std::vector<const DIE *> > AccelNamespace;
+
+ /// AccelTypes - A map of names for the type accelerator table.
+ StringMap<std::vector<std::pair<const DIE *, unsigned> > > AccelTypes;
/// DIEBlocks - A list of all the DIEBlocks in use.
std::vector<DIEBlock *> DIEBlocks;
+
+ /// DIELocs - A list of all the DIELocs in use.
+ std::vector<DIELoc *> DIELocs;
/// ContainingTypeMap - This map is used to keep track of subprogram DIEs that
/// need DW_AT_containing_type attribute. This attribute points to a DIE that
/// corresponds to the MDNode mapped with the subprogram DIE.
DenseMap<DIE *, const MDNode *> ContainingTypeMap;
+ // List of ranges for a given compile unit.
+ SmallVector<RangeSpan, 1> CURanges;
+
+ // List of range lists for a given compile unit, separate from the ranges for
+ // the CU itself.
+ SmallVector<RangeSpanList, 1> CURangeLists;
+
// DIEValueAllocator - All DIEValues are allocated through this allocator.
BumpPtrAllocator DIEValueAllocator;
// DIEIntegerOne - A preallocated DIEValue because 1 is used frequently.
DIEInteger *DIEIntegerOne;
+ /// The section this unit will be emitted in.
+ const MCSection *Section;
+
+ /// A label at the start of the non-dwo section related to this unit.
+ MCSymbol *SectionSym;
+
+ /// The start of the unit within its section.
+ MCSymbol *LabelBegin;
+
+ /// The end of the unit within its section.
+ MCSymbol *LabelEnd;
+
+ /// The label for the start of the range sets for the elements of this unit.
+ MCSymbol *LabelRange;
+
+ /// Skeleton unit associated with this unit.
+ DwarfUnit *Skeleton;
+
+ DwarfUnit(unsigned UID, DIE *D, DICompileUnit CU, AsmPrinter *A,
+ DwarfDebug *DW, DwarfFile *DWU);
+
public:
- CompileUnit(unsigned UID, DIE *D, DICompileUnit CU, AsmPrinter *A,
- DwarfDebug *DW, DwarfUnits *DWU);
- ~CompileUnit();
+ virtual ~DwarfUnit();
+
+ /// Set the skeleton unit associated with this unit.
+ void setSkeleton(DwarfUnit *Skel) { Skeleton = Skel; }
+
+ /// Get the skeleton unit associated with this unit.
+ DwarfUnit *getSkeleton() const { return Skeleton; }
+
+ /// Pass in the SectionSym even though we could recreate it in every compile
+ /// unit (type units will have actually distinct symbols once they're in
+ /// comdat sections).
+ void initSection(const MCSection *Section, MCSymbol *SectionSym) {
+ assert(!this->Section);
+ this->Section = Section;
+ this->SectionSym = SectionSym;
+ this->LabelBegin =
+ Asm->GetTempSymbol(Section->getLabelBeginName(), getUniqueID());
+ this->LabelEnd =
+ Asm->GetTempSymbol(Section->getLabelEndName(), getUniqueID());
+ this->LabelRange = Asm->GetTempSymbol("gnu_ranges", getUniqueID());
+ }
+
+ const MCSection *getSection() const {
+ assert(Section);
+ return Section;
+ }
+
+ /// If there's a skeleton then return the section symbol for the skeleton
+ /// unit, otherwise return the section symbol for this unit.
+ MCSymbol *getLocalSectionSym() const {
+ if (Skeleton)
+ return Skeleton->getSectionSym();
+ return getSectionSym();
+ }
+
+ MCSymbol *getSectionSym() const {
+ assert(Section);
+ return SectionSym;
+ }
+
+ /// If there's a skeleton then return the begin label for the skeleton unit,
+ /// otherwise return the local label for this unit.
+ MCSymbol *getLocalLabelBegin() const {
+ if (Skeleton)
+ return Skeleton->getLabelBegin();
+ return getLabelBegin();
+ }
+
+ MCSymbol *getLabelBegin() const {
+ assert(Section);
+ return LabelBegin;
+ }
+
+ MCSymbol *getLabelEnd() const {
+ assert(Section);
+ return LabelEnd;
+ }
+
+ MCSymbol *getLabelRange() const {
+ assert(Section);
+ return LabelRange;
+ }
// Accessors.
unsigned getUniqueID() const { return UniqueID; }
- uint16_t getLanguage() const { return Node.getLanguage(); }
- DICompileUnit getNode() const { return Node; }
- DIE *getCUDie() const { return CUDie.get(); }
- const StringMap<DIE *> &getGlobalNames() const { return GlobalNames; }
- const StringMap<DIE *> &getGlobalTypes() const { return GlobalTypes; }
+ uint16_t getLanguage() const { return CUNode.getLanguage(); }
+ DICompileUnit getCUNode() const { return CUNode; }
+ DIE *getUnitDie() const { return UnitDie.get(); }
+ const StringMap<const DIE *> &getGlobalNames() const { return GlobalNames; }
+ const StringMap<const DIE *> &getGlobalTypes() const { return GlobalTypes; }
- const StringMap<std::vector<DIE *> > &getAccelNames() const {
+ const StringMap<std::vector<const DIE *> > &getAccelNames() const {
return AccelNames;
}
- const StringMap<std::vector<DIE *> > &getAccelObjC() const {
+ const StringMap<std::vector<const DIE *> > &getAccelObjC() const {
return AccelObjC;
}
- const StringMap<std::vector<DIE *> > &getAccelNamespace() const {
+ const StringMap<std::vector<const DIE *> > &getAccelNamespace() const {
return AccelNamespace;
}
- const StringMap<std::vector<std::pair<DIE *, unsigned> > > &
+ const StringMap<std::vector<std::pair<const DIE *, unsigned> > > &
getAccelTypes() const {
return AccelTypes;
}
@@ -124,8 +249,23 @@ public:
void setDebugInfoOffset(unsigned DbgInfoOff) { DebugInfoOffset = DbgInfoOff; }
/// hasContent - Return true if this compile unit has something to write out.
- ///
- bool hasContent() const { return !CUDie->getChildren().empty(); }
+ bool hasContent() const { return !UnitDie->getChildren().empty(); }
+
+ /// addRange - Add an address range to the list of ranges for this unit.
+ void addRange(RangeSpan Range);
+
+ /// getRanges - Get the list of ranges for this unit.
+ const SmallVectorImpl<RangeSpan> &getRanges() const { return CURanges; }
+ SmallVectorImpl<RangeSpan> &getRanges() { return CURanges; }
+
+ /// addRangeList - Add an address range list to the list of range lists.
+ void addRangeList(RangeSpanList Ranges) { CURangeLists.push_back(Ranges); }
+
+ /// getRangeLists - Get the vector of range lists.
+ const SmallVectorImpl<RangeSpanList> &getRangeLists() const {
+ return CURangeLists;
+ }
+ SmallVectorImpl<RangeSpanList> &getRangeLists() { return CURangeLists; }
/// getParentContextString - Get a string containing the language specific
/// context for a global name.
@@ -135,24 +275,17 @@ public:
///
void addGlobalName(StringRef Name, DIE *Die, DIScope Context);
- /// addGlobalType - Add a new global type to the compile unit.
- ///
- void addGlobalType(DIType Ty);
-
- /// addPubTypes - Add a set of types from the subprogram to the global types.
- void addPubTypes(DISubprogram SP);
-
/// addAccelName - Add a new name to the name accelerator table.
- void addAccelName(StringRef Name, DIE *Die);
+ void addAccelName(StringRef Name, const DIE *Die);
/// addAccelObjC - Add a new name to the ObjC accelerator table.
- void addAccelObjC(StringRef Name, DIE *Die);
+ void addAccelObjC(StringRef Name, const DIE *Die);
/// addAccelNamespace - Add a new name to the namespace accelerator table.
- void addAccelNamespace(StringRef Name, DIE *Die);
+ void addAccelNamespace(StringRef Name, const DIE *Die);
/// addAccelType - Add a new type to the type accelerator table.
- void addAccelType(StringRef Name, std::pair<DIE *, unsigned> Die);
+ void addAccelType(StringRef Name, std::pair<const DIE *, unsigned> Die);
/// getDIE - Returns the debug information entry map slot for the
/// specified debug variable. We delegate the request to DwarfDebug
@@ -161,7 +294,8 @@ public:
/// kept in DwarfDebug.
DIE *getDIE(DIDescriptor D) const;
- DIEBlock *getDIEBlock() { return new (DIEValueAllocator) DIEBlock(); }
+ /// getDIELoc - Returns a fresh newly allocated DIELoc.
+ DIELoc *getDIELoc() { return new (DIEValueAllocator) DIELoc(); }
/// insertDIE - Insert DIE into the map. We delegate the request to DwarfDebug
/// when the MDNode can be part of the type system, since DIEs for
@@ -171,73 +305,81 @@ public:
/// addDie - Adds or interns the DIE to the compile unit.
///
- void addDie(DIE *Buffer) { CUDie->addChild(Buffer); }
+ void addDie(DIE *Buffer) { UnitDie->addChild(Buffer); }
/// addFlag - Add a flag that is true to the DIE.
void addFlag(DIE *Die, dwarf::Attribute Attribute);
/// addUInt - Add an unsigned integer attribute data and value.
- ///
void addUInt(DIE *Die, dwarf::Attribute Attribute, Optional<dwarf::Form> Form,
uint64_t Integer);
- void addUInt(DIEBlock *Block, dwarf::Form Form, uint64_t Integer);
+ void addUInt(DIE *Block, dwarf::Form Form, uint64_t Integer);
/// addSInt - Add an signed integer attribute data and value.
- ///
void addSInt(DIE *Die, dwarf::Attribute Attribute, Optional<dwarf::Form> Form,
int64_t Integer);
- void addSInt(DIEBlock *Die, Optional<dwarf::Form> Form, int64_t Integer);
+ void addSInt(DIELoc *Die, Optional<dwarf::Form> Form, int64_t Integer);
/// addString - Add a string attribute data and value.
- ///
void addString(DIE *Die, dwarf::Attribute Attribute, const StringRef Str);
/// addLocalString - Add a string attribute data and value.
- ///
- void addLocalString(DIE *Die, dwarf::Attribute Attribute, const StringRef Str);
+ void addLocalString(DIE *Die, dwarf::Attribute Attribute,
+ const StringRef Str);
/// addExpr - Add a Dwarf expression attribute data and value.
- ///
- void addExpr(DIEBlock *Die, dwarf::Form Form, const MCExpr *Expr);
+ void addExpr(DIELoc *Die, dwarf::Form Form, const MCExpr *Expr);
/// addLabel - Add a Dwarf label attribute data and value.
- ///
void addLabel(DIE *Die, dwarf::Attribute Attribute, dwarf::Form Form,
const MCSymbol *Label);
- void addLabel(DIEBlock *Die, dwarf::Form Form, const MCSymbol *Label);
+ void addLabel(DIELoc *Die, dwarf::Form Form, const MCSymbol *Label);
- /// addLabelAddress - Add a dwarf label attribute data and value using
- /// either DW_FORM_addr or DW_FORM_GNU_addr_index.
+ /// addLocationList - Add a Dwarf loclistptr attribute data and value.
+ void addLocationList(DIE *Die, dwarf::Attribute Attribute, unsigned Index);
+
+ /// addSectionLabel - Add a Dwarf section label attribute data and value.
///
- void addLabelAddress(DIE *Die, dwarf::Attribute Attribute, MCSymbol *Label);
+ void addSectionLabel(DIE *Die, dwarf::Attribute Attribute,
+ const MCSymbol *Label);
+
+ /// addSectionOffset - Add an offset into a section attribute data and value.
+ ///
+ void addSectionOffset(DIE *Die, dwarf::Attribute Attribute, uint64_t Integer);
/// addOpAddress - Add a dwarf op address data and value using the
/// form given and an op of either DW_FORM_addr or DW_FORM_GNU_addr_index.
- ///
- void addOpAddress(DIEBlock *Die, const MCSymbol *Label);
+ void addOpAddress(DIELoc *Die, const MCSymbol *Label);
- /// addDelta - Add a label delta attribute data and value.
- ///
- void addDelta(DIE *Die, dwarf::Attribute Attribute, dwarf::Form Form, const MCSymbol *Hi,
- const MCSymbol *Lo);
+ /// addSectionDelta - Add a label delta attribute data and value.
+ void addSectionDelta(DIE *Die, dwarf::Attribute Attribute, const MCSymbol *Hi,
+ const MCSymbol *Lo);
+
+ /// addLabelDelta - Add a label delta attribute data and value.
+ void addLabelDelta(DIE *Die, dwarf::Attribute Attribute, const MCSymbol *Hi,
+ const MCSymbol *Lo);
/// addDIEEntry - Add a DIE attribute data and value.
- ///
void addDIEEntry(DIE *Die, dwarf::Attribute Attribute, DIE *Entry);
/// addDIEEntry - Add a DIE attribute data and value.
- ///
void addDIEEntry(DIE *Die, dwarf::Attribute Attribute, DIEEntry *Entry);
+ void addDIETypeSignature(DIE *Die, const DwarfTypeUnit &Type);
+
+ /// addBlock - Add block data.
+ void addBlock(DIE *Die, dwarf::Attribute Attribute, DIELoc *Block);
+
/// addBlock - Add block data.
- ///
void addBlock(DIE *Die, dwarf::Attribute Attribute, DIEBlock *Block);
/// addSourceLine - Add location information to specified debug information
/// entry.
+ void addSourceLine(DIE *Die, unsigned Line, StringRef File,
+ StringRef Directory);
void addSourceLine(DIE *Die, DIVariable V);
void addSourceLine(DIE *Die, DIGlobalVariable G);
void addSourceLine(DIE *Die, DISubprogram SP);
@@ -247,8 +389,8 @@ public:
/// addAddress - Add an address attribute to a die based on the location
/// provided.
- void addAddress(DIE *Die, dwarf::Attribute Attribute, const MachineLocation &Location,
- bool Indirect = false);
+ void addAddress(DIE *Die, dwarf::Attribute Attribute,
+ const MachineLocation &Location, bool Indirect = false);
/// addConstantValue - Add constant value entry in variable DIE.
void addConstantValue(DIE *Die, const MachineOperand &MO, DIType Ty);
@@ -263,17 +405,17 @@ public:
void addTemplateParams(DIE &Buffer, DIArray TParams);
/// addRegisterOp - Add register operand.
- void addRegisterOp(DIEBlock *TheDie, unsigned Reg);
+ void addRegisterOp(DIELoc *TheDie, unsigned Reg);
/// addRegisterOffset - Add register offset.
- void addRegisterOffset(DIEBlock *TheDie, unsigned Reg, int64_t Offset);
+ void addRegisterOffset(DIELoc *TheDie, unsigned Reg, int64_t Offset);
/// addComplexAddress - Start with the address based on the location provided,
/// and generate the DWARF information necessary to find the actual variable
/// (navigating the extra location information encoded in the type) based on
/// the starting location. Add the DWARF information to the die.
- ///
- void addComplexAddress(const DbgVariable &DV, DIE *Die, dwarf::Attribute Attribute,
+ void addComplexAddress(const DbgVariable &DV, DIE *Die,
+ dwarf::Attribute Attribute,
const MachineLocation &Location);
// FIXME: Should be reformulated in terms of addComplexAddress.
@@ -282,8 +424,8 @@ public:
/// actual Block variable (navigating the Block struct) based on the
/// starting location. Add the DWARF information to the die. Obsolete,
/// please use addComplexAddress instead.
- ///
- void addBlockByrefAddress(const DbgVariable &DV, DIE *Die, dwarf::Attribute Attribute,
+ void addBlockByrefAddress(const DbgVariable &DV, DIE *Die,
+ dwarf::Attribute Attribute,
const MachineLocation &Location);
/// addVariableAddress - Add DW_AT_location attribute for a
@@ -294,7 +436,8 @@ public:
/// addType - Add a new type attribute to the specified entity. This takes
/// and attribute parameter because DW_AT_friend attributes are also
/// type references.
- void addType(DIE *Entity, DIType Ty, dwarf::Attribute Attribute = dwarf::DW_AT_type);
+ void addType(DIE *Entity, DIType Ty,
+ dwarf::Attribute Attribute = dwarf::DW_AT_type);
/// getOrCreateNameSpace - Create a DIE for DINameSpace.
DIE *getOrCreateNameSpace(DINameSpace NS);
@@ -307,10 +450,10 @@ public:
DIE *getOrCreateTypeDIE(const MDNode *N);
/// getOrCreateContextDIE - Get context owner's DIE.
- DIE *getOrCreateContextDIE(DIScope Context);
+ DIE *createTypeDIE(DICompositeType Ty);
- /// createGlobalVariableDIE - create global variable DIE.
- void createGlobalVariableDIE(DIGlobalVariable GV);
+ /// getOrCreateContextDIE - Get context owner's DIE.
+ DIE *getOrCreateContextDIE(DIScope Context);
/// constructContainingTypeDIEs - Construct DIEs for types that contain
/// vtables.
@@ -319,20 +462,34 @@ public:
/// constructVariableDIE - Construct a DIE for the given DbgVariable.
DIE *constructVariableDIE(DbgVariable &DV, bool isScopeAbstract);
+ /// constructSubprogramArguments - Construct function argument DIEs.
+ void constructSubprogramArguments(DIE &Buffer, DIArray Args);
+
/// Create a DIE with the given Tag, add the DIE to its parent, and
/// call insertDIE if MD is not null.
- DIE *createAndAddDIE(unsigned Tag, DIE &Parent, DIDescriptor N = DIDescriptor());
+ DIE *createAndAddDIE(unsigned Tag, DIE &Parent,
+ DIDescriptor N = DIDescriptor());
/// Compute the size of a header for this unit, not including the initial
/// length field.
- unsigned getHeaderSize() const {
+ virtual unsigned getHeaderSize() const {
return sizeof(int16_t) + // DWARF version number
sizeof(int32_t) + // Offset Into Abbrev. Section
sizeof(int8_t); // Pointer Size (in bytes)
}
/// Emit the header for this unit, not including the initial length field.
- void emitHeader(const MCSection *ASection, const MCSymbol *ASectionSym);
+ virtual void emitHeader(const MCSymbol *ASectionSym) const;
+
+ virtual DwarfCompileUnit &getCU() = 0;
+
+protected:
+ /// getOrCreateStaticMemberDIE - Create new static data member DIE.
+ DIE *getOrCreateStaticMemberDIE(DIDerivedType DT);
+
+ /// Look up the source ID with the given directory and source file names. If
+ /// none currently exists, create a new ID and insert it in the line table.
+ virtual unsigned getOrCreateSourceID(StringRef File, StringRef Directory) = 0;
private:
/// constructTypeDIE - Construct basic type die from DIBasicType.
@@ -366,12 +523,6 @@ private:
void constructTemplateValueParameterDIE(DIE &Buffer,
DITemplateValueParameter TVP);
- /// getOrCreateStaticMemberDIE - Create new static data member DIE.
- DIE *getOrCreateStaticMemberDIE(DIDerivedType DT);
-
- /// Offset of the CUDie from beginning of debug info section.
- unsigned DebugInfoOffset;
-
/// getLowerBoundDefault - Return the default lower bound for an array. If the
/// DWARF version doesn't handle the language, return -1.
int64_t getDefaultLowerBound() const;
@@ -403,7 +554,71 @@ private:
template <typename T> T resolve(DIRef<T> Ref) const {
return DD->resolve(Ref);
}
+
+ /// If this is a named finished type then include it in the list of types for
+ /// the accelerator tables.
+ void updateAcceleratorTables(DIScope Context, DIType Ty, const DIE *TyDIE);
};
+class DwarfCompileUnit : public DwarfUnit {
+ /// The attribute index of DW_AT_stmt_list in the compile unit DIE, avoiding
+ /// the need to search for it in applyStmtList.
+ unsigned stmtListIndex;
+
+public:
+ DwarfCompileUnit(unsigned UID, DIE *D, DICompileUnit Node, AsmPrinter *A,
+ DwarfDebug *DW, DwarfFile *DWU);
+
+ void initStmtList(MCSymbol *DwarfLineSectionSym);
+
+ /// Apply the DW_AT_stmt_list from this compile unit to the specified DIE.
+ void applyStmtList(DIE &D);
+
+ /// createGlobalVariableDIE - create global variable DIE.
+ void createGlobalVariableDIE(DIGlobalVariable GV);
+
+ /// addLabelAddress - Add a dwarf label attribute data and value using
+ /// either DW_FORM_addr or DW_FORM_GNU_addr_index.
+ void addLabelAddress(DIE *Die, dwarf::Attribute Attribute,
+ const MCSymbol *Label);
+
+ /// addLocalLabelAddress - Add a dwarf label attribute data and value using
+ /// DW_FORM_addr only.
+ void addLocalLabelAddress(DIE *Die, dwarf::Attribute Attribute,
+ const MCSymbol *Label);
+
+ DwarfCompileUnit &getCU() override { return *this; }
+
+ unsigned getOrCreateSourceID(StringRef FileName, StringRef DirName) override;
+};
+
+class DwarfTypeUnit : public DwarfUnit {
+private:
+ uint64_t TypeSignature;
+ const DIE *Ty;
+ DwarfCompileUnit &CU;
+ MCDwarfDwoLineTable *SplitLineTable;
+
+public:
+ DwarfTypeUnit(unsigned UID, DIE *D, DwarfCompileUnit &CU, AsmPrinter *A,
+ DwarfDebug *DW, DwarfFile *DWU,
+ MCDwarfDwoLineTable *SplitLineTable = nullptr);
+
+ void setTypeSignature(uint64_t Signature) { TypeSignature = Signature; }
+ uint64_t getTypeSignature() const { return TypeSignature; }
+ void setType(const DIE *Ty) { this->Ty = Ty; }
+
+ /// Emit the header for this unit, not including the initial length field.
+ void emitHeader(const MCSymbol *ASectionSym) const override;
+ unsigned getHeaderSize() const override {
+ return DwarfUnit::getHeaderSize() + sizeof(uint64_t) + // Type Signature
+ sizeof(uint32_t); // Type DIE Offset
+ }
+ void initSection(const MCSection *Section);
+ DwarfCompileUnit &getCU() override { return CU; }
+
+protected:
+ unsigned getOrCreateSourceID(StringRef File, StringRef Directory) override;
+};
} // end llvm namespace
#endif
diff --git a/lib/CodeGen/AsmPrinter/ErlangGCPrinter.cpp b/lib/CodeGen/AsmPrinter/ErlangGCPrinter.cpp
index a8fb66dcf1..bfcbe6b94e 100644
--- a/lib/CodeGen/AsmPrinter/ErlangGCPrinter.cpp
+++ b/lib/CodeGen/AsmPrinter/ErlangGCPrinter.cpp
@@ -14,8 +14,8 @@
//===----------------------------------------------------------------------===//
#include "llvm/CodeGen/AsmPrinter.h"
-#include "llvm/CodeGen/GCs.h"
#include "llvm/CodeGen/GCMetadataPrinter.h"
+#include "llvm/CodeGen/GCs.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Instruction.h"
@@ -35,8 +35,8 @@ namespace {
class ErlangGCPrinter : public GCMetadataPrinter {
public:
- void beginAssembly(AsmPrinter &AP);
- void finishAssembly(AsmPrinter &AP);
+ void beginAssembly(AsmPrinter &AP) override;
+ void finishAssembly(AsmPrinter &AP) override;
};
}
diff --git a/lib/CodeGen/AsmPrinter/LLVMBuild.txt b/lib/CodeGen/AsmPrinter/LLVMBuild.txt
index 20b1f7b45b..bbdb0c7fc3 100644
--- a/lib/CodeGen/AsmPrinter/LLVMBuild.txt
+++ b/lib/CodeGen/AsmPrinter/LLVMBuild.txt
@@ -19,4 +19,4 @@
type = Library
name = AsmPrinter
parent = Libraries
-required_libraries = Analysis CodeGen Core MC MCParser Support Target
+required_libraries = Analysis CodeGen Core MC MCParser Support Target TransformUtils
diff --git a/lib/CodeGen/AsmPrinter/OcamlGCPrinter.cpp b/lib/CodeGen/AsmPrinter/OcamlGCPrinter.cpp
index 98177c0ba1..5a9ecd794a 100644
--- a/lib/CodeGen/AsmPrinter/OcamlGCPrinter.cpp
+++ b/lib/CodeGen/AsmPrinter/OcamlGCPrinter.cpp
@@ -16,6 +16,7 @@
#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/CodeGen/GCMetadataPrinter.h"
#include "llvm/IR/DataLayout.h"
+#include "llvm/IR/Mangler.h"
#include "llvm/IR/Module.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCContext.h"
@@ -23,7 +24,6 @@
#include "llvm/MC/MCSymbol.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FormattedStream.h"
-#include "llvm/Target/Mangler.h"
#include "llvm/Target/TargetLoweringObjectFile.h"
#include "llvm/Target/TargetMachine.h"
#include <cctype>
@@ -33,8 +33,8 @@ namespace {
class OcamlGCMetadataPrinter : public GCMetadataPrinter {
public:
- void beginAssembly(AsmPrinter &AP);
- void finishAssembly(AsmPrinter &AP);
+ void beginAssembly(AsmPrinter &AP) override;
+ void finishAssembly(AsmPrinter &AP) override;
};
}
diff --git a/lib/CodeGen/AsmPrinter/Win64Exception.cpp b/lib/CodeGen/AsmPrinter/Win64Exception.cpp
index 156101286b..17d8bff609 100644
--- a/lib/CodeGen/AsmPrinter/Win64Exception.cpp
+++ b/lib/CodeGen/AsmPrinter/Win64Exception.cpp
@@ -20,6 +20,7 @@
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/IR/DataLayout.h"
+#include "llvm/IR/Mangler.h"
#include "llvm/IR/Module.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCContext.h"
@@ -30,7 +31,6 @@
#include "llvm/Support/Dwarf.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FormattedStream.h"
-#include "llvm/Target/Mangler.h"
#include "llvm/Target/TargetFrameLowering.h"
#include "llvm/Target/TargetLoweringObjectFile.h"
#include "llvm/Target/TargetOptions.h"
@@ -44,14 +44,14 @@ Win64Exception::Win64Exception(AsmPrinter *A)
Win64Exception::~Win64Exception() {}
-/// EndModule - Emit all exception information that should come after the
+/// endModule - Emit all exception information that should come after the
/// content.
-void Win64Exception::EndModule() {
+void Win64Exception::endModule() {
}
-/// BeginFunction - Gather pre-function exception information. Assumes it's
+/// beginFunction - Gather pre-function exception information. Assumes it's
/// being emitted immediately after the function entry point.
-void Win64Exception::BeginFunction(const MachineFunction *MF) {
+void Win64Exception::beginFunction(const MachineFunction *MF) {
shouldEmitMoves = shouldEmitPersonality = shouldEmitLSDA = false;
// If any landing pads survive, we need an EH table.
@@ -86,9 +86,9 @@ void Win64Exception::BeginFunction(const MachineFunction *MF) {
Asm->getFunctionNumber()));
}
-/// EndFunction - Gather and emit post-function exception information.
+/// endFunction - Gather and emit post-function exception information.
///
-void Win64Exception::EndFunction() {
+void Win64Exception::endFunction(const MachineFunction *) {
if (!shouldEmitPersonality && !shouldEmitMoves)
return;
@@ -101,7 +101,8 @@ void Win64Exception::EndFunction() {
if (shouldEmitPersonality) {
const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering();
const Function *Per = MMI->getPersonalities()[MMI->getPersonalityIndex()];
- const MCSymbol *Sym = TLOF.getCFIPersonalitySymbol(Per, Asm->Mang, MMI);
+ const MCSymbol *Sym =
+ TLOF.getCFIPersonalitySymbol(Per, *Asm->Mang, Asm->TM, MMI);
Asm->OutStreamer.PushSection();
Asm->OutStreamer.EmitWin64EHHandlerData();
diff --git a/lib/CodeGen/AsmPrinter/WinCodeViewLineTables.cpp b/lib/CodeGen/AsmPrinter/WinCodeViewLineTables.cpp
new file mode 100644
index 0000000000..50b2ca82ec
--- /dev/null
+++ b/lib/CodeGen/AsmPrinter/WinCodeViewLineTables.cpp
@@ -0,0 +1,336 @@
+//===-- llvm/lib/CodeGen/AsmPrinter/WinCodeViewLineTables.cpp --*- 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 line tables info into COFF files.
+//
+//===----------------------------------------------------------------------===//
+
+#include "WinCodeViewLineTables.h"
+#include "llvm/MC/MCExpr.h"
+#include "llvm/MC/MCSymbol.h"
+#include "llvm/Support/COFF.h"
+
+namespace llvm {
+
+StringRef WinCodeViewLineTables::getFullFilepath(const MDNode *S) {
+ assert(S);
+ DIDescriptor D(S);
+ assert((D.isCompileUnit() || D.isFile() || D.isSubprogram() ||
+ D.isLexicalBlockFile() || D.isLexicalBlock()) &&
+ "Unexpected scope info");
+
+ DIScope Scope(S);
+ StringRef Dir = Scope.getDirectory(),
+ Filename = Scope.getFilename();
+ char *&Result = DirAndFilenameToFilepathMap[std::make_pair(Dir, Filename)];
+ if (Result != 0)
+ return Result;
+
+ // Clang emits directory and relative filename info into the IR, but CodeView
+ // operates on full paths. We could change Clang to emit full paths too, but
+ // that would increase the IR size and probably not needed for other users.
+ // For now, just concatenate and canonicalize the path here.
+ std::string Filepath;
+ if (Filename.find(':') == 1)
+ Filepath = Filename;
+ else
+ Filepath = (Dir + Twine("\\") + Filename).str();
+
+ // Canonicalize the path. We have to do it textually because we may no longer
+ // have access the file in the filesystem.
+ // First, replace all slashes with backslashes.
+ std::replace(Filepath.begin(), Filepath.end(), '/', '\\');
+
+ // Remove all "\.\" with "\".
+ size_t Cursor = 0;
+ while ((Cursor = Filepath.find("\\.\\", Cursor)) != std::string::npos)
+ Filepath.erase(Cursor, 2);
+
+ // Replace all "\XXX\..\" with "\". Don't try too hard though as the original
+ // path should be well-formatted, e.g. start with a drive letter, etc.
+ Cursor = 0;
+ while ((Cursor = Filepath.find("\\..\\", Cursor)) != std::string::npos) {
+ // Something's wrong if the path starts with "\..\", abort.
+ if (Cursor == 0)
+ break;
+
+ size_t PrevSlash = Filepath.rfind('\\', Cursor - 1);
+ if (PrevSlash == std::string::npos)
+ // Something's wrong, abort.
+ break;
+
+ Filepath.erase(PrevSlash, Cursor + 3 - PrevSlash);
+ // The next ".." might be following the one we've just erased.
+ Cursor = PrevSlash;
+ }
+
+ // Remove all duplicate backslashes.
+ Cursor = 0;
+ while ((Cursor = Filepath.find("\\\\", Cursor)) != std::string::npos)
+ Filepath.erase(Cursor, 1);
+
+ Result = strdup(Filepath.c_str());
+ return StringRef(Result);
+}
+
+void WinCodeViewLineTables::maybeRecordLocation(DebugLoc DL,
+ const MachineFunction *MF) {
+ const MDNode *Scope = DL.getScope(MF->getFunction()->getContext());
+ if (!Scope)
+ return;
+ StringRef Filename = getFullFilepath(Scope);
+
+ // Skip this instruction if it has the same file:line as the previous one.
+ assert(CurFn);
+ if (!CurFn->Instrs.empty()) {
+ const InstrInfoTy &LastInstr = InstrInfo[CurFn->Instrs.back()];
+ if (LastInstr.Filename == Filename && LastInstr.LineNumber == DL.getLine())
+ return;
+ }
+ FileNameRegistry.add(Filename);
+
+ MCSymbol *MCL = Asm->MMI->getContext().CreateTempSymbol();
+ Asm->OutStreamer.EmitLabel(MCL);
+ CurFn->Instrs.push_back(MCL);
+ InstrInfo[MCL] = InstrInfoTy(Filename, DL.getLine());
+}
+
+WinCodeViewLineTables::WinCodeViewLineTables(AsmPrinter *AP)
+ : Asm(0), CurFn(0) {
+ MachineModuleInfo *MMI = AP->MMI;
+
+ // If module doesn't have named metadata anchors or COFF debug section
+ // is not available, skip any debug info related stuff.
+ if (!MMI->getModule()->getNamedMetadata("llvm.dbg.cu") ||
+ !AP->getObjFileLowering().getCOFFDebugSymbolsSection())
+ return;
+
+ // Tell MMI that we have debug info.
+ MMI->setDebugInfoAvailability(true);
+ Asm = AP;
+}
+
+static void EmitLabelDiff(MCStreamer &Streamer,
+ const MCSymbol *From, const MCSymbol *To) {
+ MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None;
+ MCContext &Context = Streamer.getContext();
+ const MCExpr *FromRef = MCSymbolRefExpr::Create(From, Variant, Context),
+ *ToRef = MCSymbolRefExpr::Create(To, Variant, Context);
+ const MCExpr *AddrDelta =
+ MCBinaryExpr::Create(MCBinaryExpr::Sub, ToRef, FromRef, Context);
+ Streamer.EmitValue(AddrDelta, 4);
+}
+
+void WinCodeViewLineTables::emitDebugInfoForFunction(const Function *GV) {
+ // For each function there is a separate subsection
+ // which holds the PC to file:line table.
+ const MCSymbol *Fn = Asm->getSymbol(GV);
+ assert(Fn);
+
+ const FunctionInfo &FI = FnDebugInfo[GV];
+ if (FI.Instrs.empty())
+ return;
+ assert(FI.End && "Don't know where the function ends?");
+
+ // PCs/Instructions are grouped into segments sharing the same filename.
+ // Pre-calculate the lengths (in instructions) of these segments and store
+ // them in a map for convenience. Each index in the map is the sequential
+ // number of the respective instruction that starts a new segment.
+ DenseMap<size_t, size_t> FilenameSegmentLengths;
+ size_t LastSegmentEnd = 0;
+ StringRef PrevFilename = InstrInfo[FI.Instrs[0]].Filename;
+ for (size_t J = 1, F = FI.Instrs.size(); J != F; ++J) {
+ if (PrevFilename == InstrInfo[FI.Instrs[J]].Filename)
+ continue;
+ FilenameSegmentLengths[LastSegmentEnd] = J - LastSegmentEnd;
+ LastSegmentEnd = J;
+ PrevFilename = InstrInfo[FI.Instrs[J]].Filename;
+ }
+ FilenameSegmentLengths[LastSegmentEnd] = FI.Instrs.size() - LastSegmentEnd;
+
+ // Emit the control code of the subsection followed by the payload size.
+ Asm->OutStreamer.AddComment(
+ "Linetable subsection for " + Twine(Fn->getName()));
+ Asm->EmitInt32(COFF::DEBUG_LINE_TABLE_SUBSECTION);
+ MCSymbol *SubsectionBegin = Asm->MMI->getContext().CreateTempSymbol(),
+ *SubsectionEnd = Asm->MMI->getContext().CreateTempSymbol();
+ EmitLabelDiff(Asm->OutStreamer, SubsectionBegin, SubsectionEnd);
+ Asm->OutStreamer.EmitLabel(SubsectionBegin);
+
+ // Identify the function this subsection is for.
+ Asm->OutStreamer.EmitCOFFSecRel32(Fn);
+ Asm->OutStreamer.EmitCOFFSectionIndex(Fn);
+
+ // Length of the function's code, in bytes.
+ EmitLabelDiff(Asm->OutStreamer, Fn, FI.End);
+
+ // PC-to-linenumber lookup table:
+ MCSymbol *FileSegmentEnd = 0;
+ for (size_t J = 0, F = FI.Instrs.size(); J != F; ++J) {
+ MCSymbol *Instr = FI.Instrs[J];
+ assert(InstrInfo.count(Instr));
+
+ if (FilenameSegmentLengths.count(J)) {
+ // We came to a beginning of a new filename segment.
+ if (FileSegmentEnd)
+ Asm->OutStreamer.EmitLabel(FileSegmentEnd);
+ StringRef CurFilename = InstrInfo[FI.Instrs[J]].Filename;
+ assert(FileNameRegistry.Infos.count(CurFilename));
+ size_t IndexInStringTable =
+ FileNameRegistry.Infos[CurFilename].FilenameID;
+ // Each segment starts with the offset of the filename
+ // in the string table.
+ Asm->OutStreamer.AddComment(
+ "Segment for file '" + Twine(CurFilename) + "' begins");
+ MCSymbol *FileSegmentBegin = Asm->MMI->getContext().CreateTempSymbol();
+ Asm->OutStreamer.EmitLabel(FileSegmentBegin);
+ Asm->EmitInt32(8 * IndexInStringTable);
+
+ // Number of PC records in the lookup table.
+ size_t SegmentLength = FilenameSegmentLengths[J];
+ Asm->EmitInt32(SegmentLength);
+
+ // Full size of the segment for this filename, including the prev two
+ // records.
+ FileSegmentEnd = Asm->MMI->getContext().CreateTempSymbol();
+ EmitLabelDiff(Asm->OutStreamer, FileSegmentBegin, FileSegmentEnd);
+ }
+
+ // The first PC with the given linenumber and the linenumber itself.
+ EmitLabelDiff(Asm->OutStreamer, Fn, Instr);
+ Asm->EmitInt32(InstrInfo[Instr].LineNumber);
+ }
+
+ if (FileSegmentEnd)
+ Asm->OutStreamer.EmitLabel(FileSegmentEnd);
+ Asm->OutStreamer.EmitLabel(SubsectionEnd);
+}
+
+void WinCodeViewLineTables::endModule() {
+ if (FnDebugInfo.empty())
+ return;
+
+ assert(Asm != 0);
+ Asm->OutStreamer.SwitchSection(
+ Asm->getObjFileLowering().getCOFFDebugSymbolsSection());
+ Asm->EmitInt32(COFF::DEBUG_SECTION_MAGIC);
+
+ // The COFF .debug$S section consists of several subsections, each starting
+ // with a 4-byte control code (e.g. 0xF1, 0xF2, etc) and then a 4-byte length
+ // of the payload followed by the payload itself. The subsections are 4-byte
+ // aligned.
+
+ for (size_t I = 0, E = VisitedFunctions.size(); I != E; ++I)
+ emitDebugInfoForFunction(VisitedFunctions[I]);
+
+ // This subsection holds a file index to offset in string table table.
+ Asm->OutStreamer.AddComment("File index to string table offset subsection");
+ Asm->EmitInt32(COFF::DEBUG_INDEX_SUBSECTION);
+ size_t NumFilenames = FileNameRegistry.Infos.size();
+ Asm->EmitInt32(8 * NumFilenames);
+ for (size_t I = 0, E = FileNameRegistry.Filenames.size(); I != E; ++I) {
+ StringRef Filename = FileNameRegistry.Filenames[I];
+ // For each unique filename, just write it's offset in the string table.
+ Asm->EmitInt32(FileNameRegistry.Infos[Filename].StartOffset);
+ // The function name offset is not followed by any additional data.
+ Asm->EmitInt32(0);
+ }
+
+ // This subsection holds the string table.
+ Asm->OutStreamer.AddComment("String table");
+ Asm->EmitInt32(COFF::DEBUG_STRING_TABLE_SUBSECTION);
+ Asm->EmitInt32(FileNameRegistry.LastOffset);
+ // The payload starts with a null character.
+ Asm->EmitInt8(0);
+
+ for (size_t I = 0, E = FileNameRegistry.Filenames.size(); I != E; ++I) {
+ // Just emit unique filenames one by one, separated by a null character.
+ Asm->OutStreamer.EmitBytes(FileNameRegistry.Filenames[I]);
+ Asm->EmitInt8(0);
+ }
+
+ // No more subsections. Fill with zeros to align the end of the section by 4.
+ Asm->OutStreamer.EmitFill((-FileNameRegistry.LastOffset) % 4, 0);
+
+ clear();
+}
+
+void WinCodeViewLineTables::beginFunction(const MachineFunction *MF) {
+ assert(!CurFn && "Can't process two functions at once!");
+
+ if (!Asm || !Asm->MMI->hasDebugInfo())
+ return;
+
+ const Function *GV = MF->getFunction();
+ assert(FnDebugInfo.count(GV) == false);
+ VisitedFunctions.push_back(GV);
+ CurFn = &FnDebugInfo[GV];
+
+ // Find the end of the function prolog.
+ // FIXME: is there a simpler a way to do this? Can we just search
+ // for the first instruction of the function, not the last of the prolog?
+ DebugLoc PrologEndLoc;
+ bool EmptyPrologue = true;
+ for (MachineFunction::const_iterator I = MF->begin(), E = MF->end();
+ I != E && PrologEndLoc.isUnknown(); ++I) {
+ for (MachineBasicBlock::const_iterator II = I->begin(), IE = I->end();
+ II != IE; ++II) {
+ const MachineInstr *MI = II;
+ if (MI->isDebugValue())
+ continue;
+
+ // First known non-DBG_VALUE and non-frame setup location marks
+ // the beginning of the function body.
+ // FIXME: do we need the first subcondition?
+ if (!MI->getFlag(MachineInstr::FrameSetup) &&
+ (!MI->getDebugLoc().isUnknown())) {
+ PrologEndLoc = MI->getDebugLoc();
+ break;
+ }
+ EmptyPrologue = false;
+ }
+ }
+ // Record beginning of function if we have a non-empty prologue.
+ if (!PrologEndLoc.isUnknown() && !EmptyPrologue) {
+ DebugLoc FnStartDL =
+ PrologEndLoc.getFnDebugLoc(MF->getFunction()->getContext());
+ maybeRecordLocation(FnStartDL, MF);
+ }
+}
+
+void WinCodeViewLineTables::endFunction(const MachineFunction *MF) {
+ if (!Asm || !CurFn) // We haven't created any debug info for this function.
+ return;
+
+ const Function *GV = MF->getFunction();
+ assert(FnDebugInfo.count(GV) == true);
+ assert(CurFn == &FnDebugInfo[GV]);
+
+ if (CurFn->Instrs.empty()) {
+ FnDebugInfo.erase(GV);
+ VisitedFunctions.pop_back();
+ } else {
+ // Define end label for subprogram.
+ MCSymbol *FunctionEndSym = Asm->OutStreamer.getContext().CreateTempSymbol();
+ Asm->OutStreamer.EmitLabel(FunctionEndSym);
+ CurFn->End = FunctionEndSym;
+ }
+ CurFn = 0;
+}
+
+void WinCodeViewLineTables::beginInstruction(const MachineInstr *MI) {
+ // Ignore DBG_VALUE locations and function prologue.
+ if (!Asm || MI->isDebugValue() || MI->getFlag(MachineInstr::FrameSetup))
+ return;
+ DebugLoc DL = MI->getDebugLoc();
+ if (DL == PrevInstLoc || DL.isUnknown())
+ return;
+ maybeRecordLocation(DL, Asm->MF);
+}
+}
diff --git a/lib/CodeGen/AsmPrinter/WinCodeViewLineTables.h b/lib/CodeGen/AsmPrinter/WinCodeViewLineTables.h
new file mode 100644
index 0000000000..a7a62053c3
--- /dev/null
+++ b/lib/CodeGen/AsmPrinter/WinCodeViewLineTables.h
@@ -0,0 +1,144 @@
+//===-- llvm/lib/CodeGen/AsmPrinter/WinCodeViewLineTables.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 support for writing line tables info into COFF files.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CODEGEN_ASMPRINTER_WINCODEVIEWLINETABLES_H__
+#define CODEGEN_ASMPRINTER_WINCODEVIEWLINETABLES_H__
+
+#include "AsmPrinterHandler.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/CodeGen/AsmPrinter.h"
+#include "llvm/CodeGen/LexicalScopes.h"
+#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/MachineModuleInfo.h"
+#include "llvm/IR/DebugInfo.h"
+#include "llvm/IR/DebugLoc.h"
+#include "llvm/MC/MCStreamer.h"
+#include "llvm/Target/TargetLoweringObjectFile.h"
+
+namespace llvm {
+/// \brief Collects and handles line tables information in a CodeView format.
+class WinCodeViewLineTables : public AsmPrinterHandler {
+ AsmPrinter *Asm;
+ DebugLoc PrevInstLoc;
+
+ // For each function, store a vector of labels to its instructions, as well as
+ // to the end of the function.
+ struct FunctionInfo {
+ SmallVector<MCSymbol *, 10> Instrs;
+ MCSymbol *End;
+ FunctionInfo() : End(0) {}
+ } *CurFn;
+
+ typedef DenseMap<const Function *, FunctionInfo> FnDebugInfoTy;
+ FnDebugInfoTy FnDebugInfo;
+ // Store the functions we've visited in a vector so we can maintain a stable
+ // order while emitting subsections.
+ SmallVector<const Function *, 10> VisitedFunctions;
+
+ // InstrInfoTy - Holds the Filename:LineNumber information for every
+ // instruction with a unique debug location.
+ struct InstrInfoTy {
+ StringRef Filename;
+ unsigned LineNumber;
+
+ InstrInfoTy() : LineNumber(0) {}
+
+ InstrInfoTy(StringRef Filename, unsigned LineNumber)
+ : Filename(Filename), LineNumber(LineNumber) {}
+ };
+ DenseMap<MCSymbol *, InstrInfoTy> InstrInfo;
+
+ // FileNameRegistry - Manages filenames observed while generating debug info
+ // by filtering out duplicates and bookkeeping the offsets in the string
+ // table to be generated.
+ struct FileNameRegistryTy {
+ SmallVector<StringRef, 10> Filenames;
+ struct PerFileInfo {
+ size_t FilenameID, StartOffset;
+ };
+ StringMap<PerFileInfo> Infos;
+
+ // The offset in the string table where we'll write the next unique
+ // filename.
+ size_t LastOffset;
+
+ FileNameRegistryTy() {
+ clear();
+ }
+
+ // Add Filename to the registry, if it was not observed before.
+ void add(StringRef Filename) {
+ if (Infos.count(Filename))
+ return;
+ size_t OldSize = Infos.size();
+ Infos[Filename].FilenameID = OldSize;
+ Infos[Filename].StartOffset = LastOffset;
+ LastOffset += Filename.size() + 1;
+ Filenames.push_back(Filename);
+ }
+
+ void clear() {
+ LastOffset = 1;
+ Infos.clear();
+ Filenames.clear();
+ }
+ } FileNameRegistry;
+
+ typedef std::map<std::pair<StringRef, StringRef>, char *>
+ DirAndFilenameToFilepathMapTy;
+ DirAndFilenameToFilepathMapTy DirAndFilenameToFilepathMap;
+ StringRef getFullFilepath(const MDNode *S);
+
+ void maybeRecordLocation(DebugLoc DL, const MachineFunction *MF);
+
+ void clear() {
+ assert(CurFn == 0);
+ FileNameRegistry.clear();
+ InstrInfo.clear();
+ }
+
+ void emitDebugInfoForFunction(const Function *GV);
+
+public:
+ WinCodeViewLineTables(AsmPrinter *Asm);
+
+ ~WinCodeViewLineTables() {
+ for (DirAndFilenameToFilepathMapTy::iterator
+ I = DirAndFilenameToFilepathMap.begin(),
+ E = DirAndFilenameToFilepathMap.end();
+ I != E; ++I)
+ free(I->second);
+ }
+
+ void setSymbolSize(const llvm::MCSymbol *, uint64_t) override {}
+
+ /// \brief Emit the COFF section that holds the line table information.
+ void endModule() override;
+
+ /// \brief Gather pre-function debug information.
+ void beginFunction(const MachineFunction *MF) override;
+
+ /// \brief Gather post-function debug information.
+ void endFunction(const MachineFunction *) override;
+
+ /// \brief Process beginning of an instruction.
+ void beginInstruction(const MachineInstr *MI) override;
+
+ /// \brief Process end of an instruction.
+ void endInstruction() override {}
+};
+} // End of namespace llvm
+
+#endif