diff options
Diffstat (limited to 'lib/CodeGen/AsmPrinter')
28 files changed, 2267 insertions, 2028 deletions
diff --git a/lib/CodeGen/AsmPrinter/ARMException.cpp b/lib/CodeGen/AsmPrinter/ARMException.cpp index 403feb4..1cb0159 100644 --- a/lib/CodeGen/AsmPrinter/ARMException.cpp +++ b/lib/CodeGen/AsmPrinter/ARMException.cpp @@ -57,10 +57,10 @@ void ARMException::endModule() { /// beginFunction - Gather pre-function exception information. Assumes it's /// being emitted immediately after the function entry point. void ARMException::beginFunction(const MachineFunction *MF) { - getTargetStreamer().emitFnStart(); - if (Asm->MF->getFunction()->needsUnwindTableEntry()) - Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("eh_func_begin", - Asm->getFunctionNumber())); + if (Asm->MAI->getExceptionHandlingType() == ExceptionHandling::ARM) + getTargetStreamer().emitFnStart(); + 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 && @@ -77,16 +77,16 @@ void ARMException::endFunction(const MachineFunction *) { if (shouldEmitCFI) Asm->OutStreamer.EmitCFIEndProc(); + // Map all labels and get rid of any dead landing pads. + MMI->TidyLandingPads(); + ARMTargetStreamer &ATS = getTargetStreamer(); - if (!Asm->MF->getFunction()->needsUnwindTableEntry()) + if (!Asm->MF->getFunction()->needsUnwindTableEntry() && + MMI->getLandingPads().empty()) ATS.emitCantUnwind(); else { Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("eh_func_end", Asm->getFunctionNumber())); - - // 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 = @@ -104,7 +104,8 @@ void ARMException::endFunction(const MachineFunction *) { } } - ATS.emitFnEnd(); + if (Asm->MAI->getExceptionHandlingType() == ExceptionHandling::ARM) + ATS.emitFnEnd(); } void ARMException::EmitTypeInfos(unsigned TTypeEncoding) { @@ -144,7 +145,7 @@ void ARMException::EmitTypeInfos(unsigned TTypeEncoding) { Asm->OutStreamer.AddComment("FilterInfo " + Twine(Entry)); } - Asm->EmitTTypeReference((TypeID == 0 ? 0 : TypeInfos[TypeID - 1]), + Asm->EmitTTypeReference((TypeID == 0 ? nullptr : TypeInfos[TypeID - 1]), TTypeEncoding); } } diff --git a/lib/CodeGen/AsmPrinter/AddressPool.cpp b/lib/CodeGen/AsmPrinter/AddressPool.cpp new file mode 100644 index 0000000..8dab5e5 --- /dev/null +++ b/lib/CodeGen/AsmPrinter/AddressPool.cpp @@ -0,0 +1,45 @@ +//===-- llvm/CodeGen/AddressPool.cpp - Dwarf Debug Framework ---*- C++ -*--===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "AddressPool.h" +#include "llvm/CodeGen/AsmPrinter.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/Target/TargetLoweringObjectFile.h" + +using namespace llvm; + +class MCExpr; + +unsigned AddressPool::getIndex(const MCSymbol *Sym, bool TLS) { + HasBeenUsed = true; + auto IterBool = + Pool.insert(std::make_pair(Sym, AddressPoolEntry(Pool.size(), TLS))); + return IterBool.first->second.Number; +} + +// Emit addresses into the section given. +void AddressPool::emit(AsmPrinter &Asm, const MCSection *AddrSection) { + if (Pool.empty()) + return; + + // Start the dwarf addr section. + Asm.OutStreamer.SwitchSection(AddrSection); + + // Order the address pool entries by ID + SmallVector<const MCExpr *, 64> Entries(Pool.size()); + + for (const auto &I : Pool) + 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()); +} diff --git a/lib/CodeGen/AsmPrinter/AddressPool.h b/lib/CodeGen/AsmPrinter/AddressPool.h new file mode 100644 index 0000000..42757d7 --- /dev/null +++ b/lib/CodeGen/AsmPrinter/AddressPool.h @@ -0,0 +1,52 @@ +//===-- llvm/CodeGen/AddressPool.h - Dwarf Debug Framework -----*- C++ -*--===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef CODEGEN_ASMPRINTER_ADDRESSPOOL_H__ +#define CODEGEN_ASMPRINTER_ADDRESSPOOL_H__ + +#include "llvm/ADT/DenseMap.h" + +namespace llvm { +class MCSection; +class MCSymbol; +class AsmPrinter; +// Collection of addresses for this unit and assorted labels. +// A Symbol->unsigned mapping of addresses used by indirect +// references. +class AddressPool { + struct AddressPoolEntry { + unsigned Number; + bool TLS; + AddressPoolEntry(unsigned Number, bool TLS) : Number(Number), TLS(TLS) {} + }; + DenseMap<const MCSymbol *, AddressPoolEntry> Pool; + + /// Record whether the AddressPool has been queried for an address index since + /// the last "resetUsedFlag" call. Used to implement type unit fallback - a + /// type that references addresses cannot be placed in a type unit when using + /// fission. + bool HasBeenUsed; + +public: + AddressPool() : HasBeenUsed(false) {} + + /// \brief Returns the index into the address pool with the given + /// label/symbol. + unsigned getIndex(const MCSymbol *Sym, bool TLS = false); + + void emit(AsmPrinter &Asm, const MCSection *AddrSection); + + bool isEmpty() { return Pool.empty(); } + + bool hasBeenUsed() const { return HasBeenUsed; } + + void resetUsedFlag() { HasBeenUsed = false; } +}; +} +#endif diff --git a/lib/CodeGen/AsmPrinter/Android.mk b/lib/CodeGen/AsmPrinter/Android.mk index a725fba..f56eb6e 100644 --- a/lib/CodeGen/AsmPrinter/Android.mk +++ b/lib/CodeGen/AsmPrinter/Android.mk @@ -8,17 +8,21 @@ codegen_asmprinter_SRC_FILES := \ include $(CLEAR_VARS) LOCAL_SRC_FILES := \ + AddressPool.cpp \ AsmPrinter.cpp \ AsmPrinterDwarf.cpp \ AsmPrinterInlineAsm.cpp \ ARMException.cpp \ + DbgValueHistoryCalculator.cpp \ DIE.cpp \ DIEHash.cpp \ DwarfAccelTable.cpp \ DwarfCFIException.cpp \ DwarfDebug.cpp \ DwarfException.cpp \ - DwarfUnit.cpp \ + DwarfFile.cpp \ + DwarfStringPool.cpp \ + DwarfUnit.cpp \ ErlangGCPrinter.cpp \ OcamlGCPrinter.cpp \ Win64Exception.cpp \ @@ -38,17 +42,21 @@ ifneq (true,$(DISABLE_LLVM_DEVICE_BUILDS)) include $(CLEAR_VARS) LOCAL_SRC_FILES := \ + AddressPool.cpp \ AsmPrinter.cpp \ AsmPrinterDwarf.cpp \ AsmPrinterInlineAsm.cpp \ ARMException.cpp \ + DbgValueHistoryCalculator.cpp \ DIE.cpp \ DIEHash.cpp \ DwarfAccelTable.cpp \ DwarfCFIException.cpp \ DwarfDebug.cpp \ DwarfException.cpp \ - DwarfUnit.cpp \ + DwarfFile.cpp \ + DwarfStringPool.cpp \ + DwarfUnit.cpp \ ErlangGCPrinter.cpp \ OcamlGCPrinter.cpp \ Win64Exception.cpp \ diff --git a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index c3afc8b..7de9c6d 100644 --- a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -11,7 +11,6 @@ // //===----------------------------------------------------------------------===// -#define DEBUG_TYPE "asm-printer" #include "llvm/CodeGen/AsmPrinter.h" #include "DwarfDebug.h" #include "DwarfException.h" @@ -53,6 +52,8 @@ #include "llvm/Transforms/Utils/GlobalStatus.h" using namespace llvm; +#define DEBUG_TYPE "asm-printer" + static const char *const DWARFGroupName = "DWARF Emission"; static const char *const DbgTimerName = "Debug Info Emission"; static const char *const EHTimerName = "DWARF Exception Writer"; @@ -62,9 +63,9 @@ STATISTIC(EmittedInsts, "Number of machine instrs printed"); char AsmPrinter::ID = 0; -typedef DenseMap<GCStrategy*,GCMetadataPrinter*> gcp_map_type; +typedef DenseMap<GCStrategy*, std::unique_ptr<GCMetadataPrinter>> gcp_map_type; static gcp_map_type &getGCMap(void *&P) { - if (P == 0) + if (!P) P = new gcp_map_type(); return *(gcp_map_type*)P; } @@ -101,23 +102,21 @@ AsmPrinter::AsmPrinter(TargetMachine &tm, MCStreamer &Streamer) TM(tm), MAI(tm.getMCAsmInfo()), MII(tm.getInstrInfo()), OutContext(Streamer.getContext()), OutStreamer(Streamer), - LastMI(0), LastFn(0), Counter(~0U), SetCounter(0) { - DD = 0; MMI = 0; LI = 0; MF = 0; - CurrentFnSym = CurrentFnSymForSize = 0; - GCMetadataPrinters = 0; + LastMI(nullptr), LastFn(0), Counter(~0U), SetCounter(0) { + DD = nullptr; MMI = nullptr; LI = nullptr; MF = nullptr; + CurrentFnSym = CurrentFnSymForSize = nullptr; + GCMetadataPrinters = nullptr; VerboseAsm = Streamer.isVerboseAsm(); } AsmPrinter::~AsmPrinter() { - assert(DD == 0 && Handlers.empty() && "Debug/EH info didn't get finalized"); + assert(!DD && Handlers.empty() && "Debug/EH info didn't get finalized"); - if (GCMetadataPrinters != 0) { + if (GCMetadataPrinters) { gcp_map_type &GCMap = getGCMap(GCMetadataPrinters); - for (gcp_map_type::iterator I = GCMap.begin(), E = GCMap.end(); I != E; ++I) - delete I->second; delete &GCMap; - GCMetadataPrinters = 0; + GCMetadataPrinters = nullptr; } delete &OutStreamer; @@ -209,7 +208,7 @@ bool AsmPrinter::doInitialization(Module &M) { GCModuleInfo *MI = getAnalysisIfAvailable<GCModuleInfo>(); assert(MI && "AsmPrinter didn't require GCModuleInfo?"); - for (GCModuleInfo::iterator I = MI->begin(), E = MI->end(); I != E; ++I) + for (auto &I : *MI) if (GCMetadataPrinter *MP = GetOrCreateGCPrinter(*I)) MP->beginAssembly(*this); @@ -233,7 +232,7 @@ bool AsmPrinter::doInitialization(Module &M) { } } - DwarfException *DE = 0; + DwarfException *DE = nullptr; switch (MAI->getExceptionHandlingType()) { case ExceptionHandling::None: break; @@ -370,10 +369,9 @@ void AsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) { // sections and expected to be contiguous (e.g. ObjC metadata). unsigned AlignLog = getGVAlignmentLog2(GV, *DL); - 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); + for (const HandlerInfo &HI : Handlers) { + NamedRegionTimer T(HI.TimerName, HI.TimerGroupName, TimePassesIsEnabled); + HI.Handler->setSymbolSize(GVSym, Size); } // Handle common and BSS local symbols (.lcomm). @@ -545,10 +543,9 @@ void AsmPrinter::EmitFunctionHeader() { } // Emit pre-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->beginFunction(MF); + for (const HandlerInfo &HI : Handlers) { + NamedRegionTimer T(HI.TimerName, HI.TimerGroupName, TimePassesIsEnabled); + HI.Handler->beginFunction(MF); } // Emit the prefix data. @@ -746,69 +743,65 @@ void AsmPrinter::EmitFunctionBody() { // Print out code for the function. bool HasAnyRealCode = false; - const MachineInstr *LastMI = 0; - for (MachineFunction::const_iterator I = MF->begin(), E = MF->end(); - I != E; ++I) { + const MachineInstr *LastMI = nullptr; + for (auto &MBB : *MF) { // Print a label for the basic block. - EmitBasicBlockStart(I); - for (MachineBasicBlock::const_iterator II = I->begin(), IE = I->end(); - II != IE; ++II) { - LastMI = II; + EmitBasicBlockStart(MBB); + for (auto &MI : MBB) { + LastMI = &MI; // Print the assembly for the instruction. - if (!II->isPosition() && !II->isImplicitDef() && !II->isKill() && - !II->isDebugValue()) { + if (!MI.isPosition() && !MI.isImplicitDef() && !MI.isKill() && + !MI.isDebugValue()) { HasAnyRealCode = true; ++EmittedInsts; } if (ShouldPrintDebugScopes) { - for (unsigned III = 0, EEE = Handlers.size(); III != EEE; ++III) { - const HandlerInfo &OI = Handlers[III]; - NamedRegionTimer T(OI.TimerName, OI.TimerGroupName, + for (const HandlerInfo &HI : Handlers) { + NamedRegionTimer T(HI.TimerName, HI.TimerGroupName, TimePassesIsEnabled); - OI.Handler->beginInstruction(II); + HI.Handler->beginInstruction(&MI); } } if (isVerbose()) - emitComments(*II, OutStreamer.GetCommentOS()); + emitComments(MI, OutStreamer.GetCommentOS()); - switch (II->getOpcode()) { + switch (MI.getOpcode()) { case TargetOpcode::CFI_INSTRUCTION: - emitCFIInstruction(*II); + emitCFIInstruction(MI); break; case TargetOpcode::EH_LABEL: case TargetOpcode::GC_LABEL: - OutStreamer.EmitLabel(II->getOperand(0).getMCSymbol()); + OutStreamer.EmitLabel(MI.getOperand(0).getMCSymbol()); break; case TargetOpcode::INLINEASM: - EmitInlineAsm(II); + EmitInlineAsm(&MI); break; case TargetOpcode::DBG_VALUE: if (isVerbose()) { - if (!emitDebugValueComment(II, *this)) - EmitInstruction(II); + if (!emitDebugValueComment(&MI, *this)) + EmitInstruction(&MI); } break; case TargetOpcode::IMPLICIT_DEF: - if (isVerbose()) emitImplicitDef(II); + if (isVerbose()) emitImplicitDef(&MI); break; case TargetOpcode::KILL: - if (isVerbose()) emitKill(II, *this); + if (isVerbose()) emitKill(&MI, *this); break; default: - EmitInstruction(II); + EmitInstruction(&MI); break; } if (ShouldPrintDebugScopes) { - for (unsigned III = 0, EEE = Handlers.size(); III != EEE; ++III) { - const HandlerInfo &OI = Handlers[III]; - NamedRegionTimer T(OI.TimerName, OI.TimerGroupName, + for (const HandlerInfo &HI : Handlers) { + NamedRegionTimer T(HI.TimerName, HI.TimerGroupName, TimePassesIsEnabled); - OI.Handler->endInstruction(); + HI.Handler->endInstruction(); } } } @@ -835,11 +828,10 @@ void AsmPrinter::EmitFunctionBody() { } const Function *F = MF->getFunction(); - for (Function::const_iterator i = F->begin(), e = F->end(); i != e; ++i) { - const BasicBlock *BB = i; - if (!BB->hasAddressTaken()) + for (const auto &BB : *F) { + if (!BB.hasAddressTaken()) continue; - MCSymbol *Sym = GetBlockAddressSymbol(BB); + MCSymbol *Sym = GetBlockAddressSymbol(&BB); if (Sym->isDefined()) continue; OutStreamer.AddComment("Address of block that was removed by CodeGen"); @@ -866,10 +858,9 @@ void AsmPrinter::EmitFunctionBody() { } // 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); + for (const HandlerInfo &HI : Handlers) { + NamedRegionTimer T(HI.TimerName, HI.TimerGroupName, TimePassesIsEnabled); + HI.Handler->endFunction(MF); } MMI->EndFunction(); @@ -881,13 +872,11 @@ void AsmPrinter::EmitFunctionBody() { bool AsmPrinter::doFinalization(Module &M) { // Emit global variables. - for (Module::const_global_iterator I = M.global_begin(), E = M.global_end(); - I != E; ++I) - EmitGlobalVariable(I); + for (const auto &G : M.globals()) + EmitGlobalVariable(&G); // Emit visibility info for declarations - for (Module::const_iterator I = M.begin(), E = M.end(); I != E; ++I) { - const Function &F = *I; + for (const Function &F : M) { if (!F.isDeclaration()) continue; GlobalValue::VisibilityTypes V = F.getVisibility(); @@ -908,15 +897,14 @@ bool AsmPrinter::doFinalization(Module &M) { OutStreamer.Flush(); // Finalize debug and EH information. - for (unsigned I = 0, E = Handlers.size(); I != E; ++I) { - const HandlerInfo &OI = Handlers[I]; - NamedRegionTimer T(OI.TimerName, OI.TimerGroupName, + for (const HandlerInfo &HI : Handlers) { + NamedRegionTimer T(HI.TimerName, HI.TimerGroupName, TimePassesIsEnabled); - OI.Handler->endModule(); - delete OI.Handler; + HI.Handler->endModule(); + delete HI.Handler; } Handlers.clear(); - DD = 0; + DD = nullptr; // If the target wants to know about weak references, print them all. if (MAI->getWeakRefDirective()) { @@ -926,36 +914,36 @@ bool AsmPrinter::doFinalization(Module &M) { // happen with the MC stuff eventually. // Print out module-level global variables here. - for (Module::const_global_iterator I = M.global_begin(), E = M.global_end(); - I != E; ++I) { - if (!I->hasExternalWeakLinkage()) continue; - OutStreamer.EmitSymbolAttribute(getSymbol(I), MCSA_WeakReference); + for (const auto &G : M.globals()) { + if (!G.hasExternalWeakLinkage()) + continue; + OutStreamer.EmitSymbolAttribute(getSymbol(&G), MCSA_WeakReference); } - for (Module::const_iterator I = M.begin(), E = M.end(); I != E; ++I) { - if (!I->hasExternalWeakLinkage()) continue; - OutStreamer.EmitSymbolAttribute(getSymbol(I), MCSA_WeakReference); + for (const auto &F : M) { + if (!F.hasExternalWeakLinkage()) + continue; + OutStreamer.EmitSymbolAttribute(getSymbol(&F), MCSA_WeakReference); } } if (MAI->hasSetDirective()) { OutStreamer.AddBlankLine(); - for (Module::const_alias_iterator I = M.alias_begin(), E = M.alias_end(); - I != E; ++I) { - MCSymbol *Name = getSymbol(I); + for (const auto &Alias : M.aliases()) { + MCSymbol *Name = getSymbol(&Alias); - const GlobalValue *GV = I->getAliasedGlobal(); + const GlobalValue *GV = Alias.getAliasee(); assert(!GV->isDeclaration()); MCSymbol *Target = getSymbol(GV); - if (I->hasExternalLinkage() || !MAI->getWeakRefDirective()) + if (Alias.hasExternalLinkage() || !MAI->getWeakRefDirective()) OutStreamer.EmitSymbolAttribute(Name, MCSA_Global); - else if (I->hasWeakLinkage() || I->hasLinkOnceLinkage()) + else if (Alias.hasWeakLinkage() || Alias.hasLinkOnceLinkage()) OutStreamer.EmitSymbolAttribute(Name, MCSA_WeakReference); else - assert(I->hasLocalLinkage() && "Invalid alias linkage"); + assert(Alias.hasLocalLinkage() && "Invalid alias linkage"); - EmitVisibility(Name, I->getVisibility()); + EmitVisibility(Name, Alias.getVisibility()); // Emit the directives as assignments aka .set: OutStreamer.EmitAssignment(Name, @@ -966,7 +954,7 @@ bool AsmPrinter::doFinalization(Module &M) { GCModuleInfo *MI = getAnalysisIfAvailable<GCModuleInfo>(); assert(MI && "AsmPrinter didn't require GCModuleInfo?"); for (GCModuleInfo::iterator I = MI->end(), E = MI->begin(); I != E; ) - if (GCMetadataPrinter *MP = GetOrCreateGCPrinter(*--I)) + if (GCMetadataPrinter *MP = GetOrCreateGCPrinter(**--I)) MP->finishAssembly(*this); // Emit llvm.ident metadata in an '.ident' directive. @@ -983,8 +971,8 @@ bool AsmPrinter::doFinalization(Module &M) { // after everything else has gone out. EmitEndOfAsmFile(M); - delete Mang; Mang = 0; - MMI = 0; + delete Mang; Mang = nullptr; + MMI = nullptr; OutStreamer.Finish(); OutStreamer.reset(); @@ -1100,7 +1088,7 @@ void AsmPrinter::EmitConstantPool() { void AsmPrinter::EmitJumpTableInfo() { const DataLayout *DL = MF->getTarget().getDataLayout(); const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo(); - if (MJTI == 0) return; + if (!MJTI) return; if (MJTI->getEntryKind() == MachineJumpTableInfo::EK_Inline) return; const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables(); if (JT.empty()) return; @@ -1185,7 +1173,7 @@ void AsmPrinter::EmitJumpTableEntry(const MachineJumpTableInfo *MJTI, const MachineBasicBlock *MBB, unsigned UID) const { assert(MBB && MBB->getNumber() >= 0 && "Invalid basic block"); - const MCExpr *Value = 0; + const MCExpr *Value = nullptr; switch (MJTI->getEntryKind()) { case MachineJumpTableInfo::EK_Inline: llvm_unreachable("Cannot emit EK_Inline jump table entry"); @@ -1308,6 +1296,15 @@ void AsmPrinter::EmitLLVMUsedList(const ConstantArray *InitList) { } } +namespace { +struct Structor { + Structor() : Priority(0), Func(nullptr), ComdatKey(nullptr) {} + int Priority; + llvm::Constant *Func; + llvm::GlobalValue *ComdatKey; +}; +} // end namespace + /// EmitXXStructorList - Emit the ctor or dtor list taking into account the init /// priority. void AsmPrinter::EmitXXStructorList(const Constant *List, bool isCtor) { @@ -1319,37 +1316,52 @@ void AsmPrinter::EmitXXStructorList(const Constant *List, bool isCtor) { const ConstantArray *InitList = dyn_cast<ConstantArray>(List); if (!InitList) return; // Not an array! StructType *ETy = dyn_cast<StructType>(InitList->getType()->getElementType()); - if (!ETy || ETy->getNumElements() != 2) return; // Not an array of pairs! + // FIXME: Only allow the 3-field form in LLVM 4.0. + if (!ETy || ETy->getNumElements() < 2 || ETy->getNumElements() > 3) + return; // Not an array of two or three elements! if (!isa<IntegerType>(ETy->getTypeAtIndex(0U)) || !isa<PointerType>(ETy->getTypeAtIndex(1U))) return; // Not (int, ptr). + if (ETy->getNumElements() == 3 && !isa<PointerType>(ETy->getTypeAtIndex(2U))) + return; // Not (int, ptr, ptr). // Gather the structors in a form that's convenient for sorting by priority. - typedef std::pair<unsigned, Constant *> Structor; SmallVector<Structor, 8> Structors; - for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) { - ConstantStruct *CS = dyn_cast<ConstantStruct>(InitList->getOperand(i)); + for (Value *O : InitList->operands()) { + ConstantStruct *CS = dyn_cast<ConstantStruct>(O); if (!CS) continue; // Malformed. if (CS->getOperand(1)->isNullValue()) break; // Found a null terminator, skip the rest. ConstantInt *Priority = dyn_cast<ConstantInt>(CS->getOperand(0)); if (!Priority) continue; // Malformed. - Structors.push_back(std::make_pair(Priority->getLimitedValue(65535), - CS->getOperand(1))); + Structors.push_back(Structor()); + Structor &S = Structors.back(); + S.Priority = Priority->getLimitedValue(65535); + S.Func = CS->getOperand(1); + if (ETy->getNumElements() == 3 && !CS->getOperand(2)->isNullValue()) + S.ComdatKey = dyn_cast<GlobalValue>(CS->getOperand(2)->stripPointerCasts()); } // Emit the function pointers in the target-specific order const DataLayout *DL = TM.getDataLayout(); unsigned Align = Log2_32(DL->getPointerPrefAlignment()); - std::stable_sort(Structors.begin(), Structors.end(), less_first()); - for (unsigned i = 0, e = Structors.size(); i != e; ++i) { + std::stable_sort(Structors.begin(), Structors.end(), + [](const Structor &L, + const Structor &R) { return L.Priority < R.Priority; }); + for (Structor &S : Structors) { + const TargetLoweringObjectFile &Obj = getObjFileLowering(); + const MCSymbol *KeySym = nullptr; + const MCSection *KeySec = nullptr; + if (S.ComdatKey) { + KeySym = getSymbol(S.ComdatKey); + KeySec = getObjFileLowering().SectionForGlobal(S.ComdatKey, *Mang, TM); + } const MCSection *OutputSection = - (isCtor ? - getObjFileLowering().getStaticCtorSection(Structors[i].first) : - getObjFileLowering().getStaticDtorSection(Structors[i].first)); + (isCtor ? Obj.getStaticCtorSection(S.Priority, KeySym, KeySec) + : Obj.getStaticDtorSection(S.Priority, KeySym, KeySec)); OutStreamer.SwitchSection(OutputSection); if (OutStreamer.getCurrentSection() != OutStreamer.getPreviousSection()) EmitAlignment(Align); - EmitXXStructor(Structors[i].second); + EmitXXStructor(S.Func); } } @@ -1470,7 +1482,7 @@ void AsmPrinter::EmitLabelPlusOffset(const MCSymbol *Label, uint64_t Offset, // an explicit alignment requested, it will override the alignment request // if required for correctness. // -void AsmPrinter::EmitAlignment(unsigned NumBits, const GlobalValue *GV) const { +void AsmPrinter::EmitAlignment(unsigned NumBits, const GlobalObject *GV) const { if (GV) NumBits = getGVAlignmentLog2(GV, *TM.getDataLayout(), NumBits); if (NumBits == 0) return; // 1-byte aligned: no need to emit alignment. @@ -1503,7 +1515,7 @@ static const MCExpr *lowerConstant(const Constant *CV, AsmPrinter &AP) { return MCSymbolRefExpr::Create(AP.GetBlockAddressSymbol(BA), Ctx); const ConstantExpr *CE = dyn_cast<ConstantExpr>(CV); - if (CE == 0) { + if (!CE) { llvm_unreachable("Unknown constant value to lower!"); } @@ -1528,7 +1540,7 @@ static const MCExpr *lowerConstant(const Constant *CV, AsmPrinter &AP) { raw_string_ostream OS(S); OS << "Unsupported expression in static initializer: "; CE->printAsOperand(OS, /*PrintType=*/false, - !AP.MF ? 0 : AP.MF->getFunction()->getParent()); + !AP.MF ? nullptr : AP.MF->getFunction()->getParent()); report_fatal_error(OS.str()); } case Instruction::GetElementPtr: { @@ -2055,7 +2067,7 @@ MCSymbol *AsmPrinter::GetExternalSymbolSymbol(StringRef Sym) const { /// PrintParentLoopComment - Print comments about parent loops of this one. static void PrintParentLoopComment(raw_ostream &OS, const MachineLoop *Loop, unsigned FunctionNumber) { - if (Loop == 0) return; + if (!Loop) return; PrintParentLoopComment(OS, Loop->getParentLoop(), FunctionNumber); OS.indent(Loop->getLoopDepth()*2) << "Parent Loop BB" << FunctionNumber << "_" @@ -2069,12 +2081,12 @@ static void PrintParentLoopComment(raw_ostream &OS, const MachineLoop *Loop, static void PrintChildLoopComment(raw_ostream &OS, const MachineLoop *Loop, unsigned FunctionNumber) { // Add child loop information - for (MachineLoop::iterator CL = Loop->begin(), E = Loop->end();CL != E; ++CL){ - OS.indent((*CL)->getLoopDepth()*2) + for (const MachineLoop *CL : *Loop) { + OS.indent(CL->getLoopDepth()*2) << "Child Loop BB" << FunctionNumber << "_" - << (*CL)->getHeader()->getNumber() << " Depth " << (*CL)->getLoopDepth() + << CL->getHeader()->getNumber() << " Depth " << CL->getLoopDepth() << '\n'; - PrintChildLoopComment(OS, *CL, FunctionNumber); + PrintChildLoopComment(OS, CL, FunctionNumber); } } @@ -2084,7 +2096,7 @@ static void emitBasicBlockLoopComments(const MachineBasicBlock &MBB, const AsmPrinter &AP) { // Add loop depth information const MachineLoop *Loop = LI->getLoopFor(&MBB); - if (Loop == 0) return; + if (!Loop) return; MachineBasicBlock *Header = Loop->getHeader(); assert(Header && "No header for loop"); @@ -2120,42 +2132,41 @@ static void emitBasicBlockLoopComments(const MachineBasicBlock &MBB, /// EmitBasicBlockStart - This method prints the label for the specified /// MachineBasicBlock, an alignment (if present) and a comment describing /// it if appropriate. -void AsmPrinter::EmitBasicBlockStart(const MachineBasicBlock *MBB) const { +void AsmPrinter::EmitBasicBlockStart(const MachineBasicBlock &MBB) const { // Emit an alignment directive for this block, if needed. - if (unsigned Align = MBB->getAlignment()) + if (unsigned Align = MBB.getAlignment()) EmitAlignment(Align); // If the block has its address taken, emit any labels that were used to // reference the block. It is possible that there is more than one label // here, because multiple LLVM BB's may have been RAUW'd to this block after // the references were generated. - if (MBB->hasAddressTaken()) { - const BasicBlock *BB = MBB->getBasicBlock(); + if (MBB.hasAddressTaken()) { + const BasicBlock *BB = MBB.getBasicBlock(); if (isVerbose()) OutStreamer.AddComment("Block address taken"); - std::vector<MCSymbol*> Syms = MMI->getAddrLabelSymbolToEmit(BB); - - for (unsigned i = 0, e = Syms.size(); i != e; ++i) - OutStreamer.EmitLabel(Syms[i]); + std::vector<MCSymbol*> Symbols = MMI->getAddrLabelSymbolToEmit(BB); + for (auto *Sym : Symbols) + OutStreamer.EmitLabel(Sym); } // Print some verbose block comments. if (isVerbose()) { - if (const BasicBlock *BB = MBB->getBasicBlock()) + if (const BasicBlock *BB = MBB.getBasicBlock()) if (BB->hasName()) OutStreamer.AddComment("%" + BB->getName()); - emitBasicBlockLoopComments(*MBB, LI, *this); + emitBasicBlockLoopComments(MBB, LI, *this); } // Print the main label for the block. - if (MBB->pred_empty() || isBlockOnlyReachableByFallthrough(MBB)) { + if (MBB.pred_empty() || isBlockOnlyReachableByFallthrough(&MBB)) { if (isVerbose()) { // NOTE: Want this comment at start of line, don't emit with AddComment. - OutStreamer.emitRawComment(" BB#" + Twine(MBB->getNumber()) + ":", false); + OutStreamer.emitRawComment(" BB#" + Twine(MBB.getNumber()) + ":", false); } } else { - OutStreamer.EmitLabel(MBB->getSymbol()); + OutStreamer.EmitLabel(MBB.getSymbol()); } } @@ -2191,14 +2202,11 @@ isBlockOnlyReachableByFallthrough(const MachineBasicBlock *MBB) const { return false; // If there isn't exactly one predecessor, it can't be a fall through. - MachineBasicBlock::const_pred_iterator PI = MBB->pred_begin(), PI2 = PI; - ++PI2; - if (PI2 != MBB->pred_end()) + if (MBB->pred_size() > 1) return false; // The predecessor has to be immediately before this block. - MachineBasicBlock *Pred = *PI; - + MachineBasicBlock *Pred = *MBB->pred_begin(); if (!Pred->isLayoutSuccessor(MBB)) return false; @@ -2207,10 +2215,7 @@ isBlockOnlyReachableByFallthrough(const MachineBasicBlock *MBB) const { return true; // Check the terminators in the previous blocks - for (MachineBasicBlock::iterator II = Pred->getFirstTerminator(), - IE = Pred->end(); II != IE; ++II) { - MachineInstr &MI = *II; - + for (const auto &MI : Pred->terminators()) { // If it is not a simple branch, we are in a table somewhere. if (!MI.isBranch() || MI.isIndirectBranch()) return false; @@ -2231,25 +2236,25 @@ isBlockOnlyReachableByFallthrough(const MachineBasicBlock *MBB) const { -GCMetadataPrinter *AsmPrinter::GetOrCreateGCPrinter(GCStrategy *S) { - if (!S->usesMetadata()) - return 0; +GCMetadataPrinter *AsmPrinter::GetOrCreateGCPrinter(GCStrategy &S) { + if (!S.usesMetadata()) + return nullptr; gcp_map_type &GCMap = getGCMap(GCMetadataPrinters); - gcp_map_type::iterator GCPI = GCMap.find(S); + gcp_map_type::iterator GCPI = GCMap.find(&S); if (GCPI != GCMap.end()) - return GCPI->second; + return GCPI->second.get(); - const char *Name = S->getName().c_str(); + const char *Name = S.getName().c_str(); for (GCMetadataPrinterRegistry::iterator I = GCMetadataPrinterRegistry::begin(), E = GCMetadataPrinterRegistry::end(); I != E; ++I) if (strcmp(Name, I->getName()) == 0) { - GCMetadataPrinter *GMP = I->instantiate(); - GMP->S = S; - GCMap.insert(std::make_pair(S, GMP)); - return GMP; + std::unique_ptr<GCMetadataPrinter> GMP = I->instantiate(); + GMP->S = &S; + auto IterBool = GCMap.insert(std::make_pair(&S, std::move(GMP))); + return IterBool.first->second.get(); } report_fatal_error("no GCMetadataPrinter registered for GC: " + Twine(Name)); diff --git a/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp b/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp index b696069..02cd12b 100644 --- a/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp +++ b/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp @@ -11,7 +11,6 @@ // //===----------------------------------------------------------------------===// -#define DEBUG_TYPE "asm-printer" #include "ByteStreamer.h" #include "llvm/CodeGen/AsmPrinter.h" #include "llvm/ADT/SmallBitVector.h" @@ -30,6 +29,8 @@ #include "llvm/Target/TargetRegisterInfo.h" using namespace llvm; +#define DEBUG_TYPE "asm-printer" + //===----------------------------------------------------------------------===// // Dwarf Emission Helper Routines //===----------------------------------------------------------------------===// @@ -216,30 +217,48 @@ static void emitDwarfRegOpIndirect(ByteStreamer &Streamer, int Reg, int Offset, /// 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) { +static void emitDwarfOpPiece(ByteStreamer &Streamer, unsigned SizeInBits, + unsigned OffsetInBits) { + assert(SizeInBits > 0 && "zero-sized piece"); + unsigned SizeOfByte = 8; + if (OffsetInBits > 0 || SizeInBits % SizeOfByte) { Streamer.EmitInt8(dwarf::DW_OP_bit_piece, "DW_OP_bit_piece"); - Streamer.EmitULEB128(Size, Twine(Size)); - Streamer.EmitULEB128(Offset, Twine(Offset)); + Streamer.EmitULEB128(SizeInBits, Twine(SizeInBits)); + Streamer.EmitULEB128(OffsetInBits, Twine(OffsetInBits)); } else { Streamer.EmitInt8(dwarf::DW_OP_piece, "DW_OP_piece"); - unsigned ByteSize = Size / 8; // Assuming 8 bits per byte. + unsigned ByteSize = SizeInBits / SizeOfByte; 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(); +/// Emit a shift-right dwarf expression. +static void emitDwarfOpShr(ByteStreamer &Streamer, + unsigned ShiftBy) { + Streamer.EmitInt8(dwarf::DW_OP_constu, "DW_OP_constu"); + Streamer.EmitULEB128(ShiftBy); + Streamer.EmitInt8(dwarf::DW_OP_shr, "DW_OP_shr"); +} + +// 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. +void AsmPrinter::EmitDwarfRegOpPiece(ByteStreamer &Streamer, + const MachineLocation &MLoc, + unsigned PieceSizeInBits, + unsigned PieceOffsetInBits) const { + assert(MLoc.isReg() && "MLoc must be a register"); + const TargetRegisterInfo *TRI = TM.getRegisterInfo(); int Reg = TRI->getDwarfRegNum(MLoc.getReg(), false); + // If this is a valid register number, emit it. + if (Reg >= 0) { + emitDwarfRegOp(Streamer, Reg); + emitDwarfOpPiece(Streamer, PieceSizeInBits, PieceOffsetInBits); + return; + } + // 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) { @@ -248,9 +267,19 @@ static void EmitDwarfRegOpPiece(ByteStreamer &Streamer, const AsmPrinter &AP, unsigned Idx = TRI->getSubRegIndex(*SR, MLoc.getReg()); unsigned Size = TRI->getSubRegIdxSize(Idx); unsigned Offset = TRI->getSubRegIdxOffset(Idx); - AP.OutStreamer.AddComment("super-register"); + OutStreamer.AddComment("super-register"); emitDwarfRegOp(Streamer, Reg); - emitDwarfOpPiece(Streamer, Size, Offset); + if (PieceOffsetInBits == Offset) { + emitDwarfOpPiece(Streamer, Size, Offset); + } else { + // If this is part of a variable in a sub-register at a + // non-zero offset, we need to manually shift the value into + // place, since the DW_OP_piece describes the part of the + // variable, not the position of the subregister. + emitDwarfOpPiece(Streamer, Size, PieceOffsetInBits); + if (Offset) + emitDwarfOpShr(Streamer, Offset); + } return; } } @@ -260,7 +289,7 @@ static void EmitDwarfRegOpPiece(ByteStreamer &Streamer, const AsmPrinter &AP, // // Keep track of the current position so we can emit the more // efficient DW_OP_piece. - unsigned CurPos = 0; + unsigned CurPos = PieceOffsetInBits; // 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 @@ -281,7 +310,7 @@ static void EmitDwarfRegOpPiece(ByteStreamer &Streamer, const AsmPrinter &AP, // 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"); + OutStreamer.AddComment("sub-register"); emitDwarfRegOp(Streamer, Reg); emitDwarfOpPiece(Streamer, Size, Offset == CurPos ? 0 : Offset); CurPos = Offset + Size; @@ -291,7 +320,7 @@ static void EmitDwarfRegOpPiece(ByteStreamer &Streamer, const AsmPrinter &AP, } } - if (CurPos == 0) { + if (CurPos == PieceOffsetInBits) { // 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)"); @@ -317,8 +346,7 @@ void AsmPrinter::EmitDwarfRegOp(ByteStreamer &Streamer, } // Attempt to find a valid super- or sub-register. - if (!Indirect && !MLoc.isIndirect()) - return EmitDwarfRegOpPiece(Streamer, *this, MLoc); + return EmitDwarfRegOpPiece(Streamer, MLoc); } if (MLoc.isIndirect()) diff --git a/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp b/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp index 567b6e3..46ee0c8 100644 --- a/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp +++ b/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp @@ -11,11 +11,11 @@ // //===----------------------------------------------------------------------===// -#define DEBUG_TYPE "asm-printer" #include "llvm/CodeGen/AsmPrinter.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/Twine.h" #include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/IR/Constants.h" #include "llvm/IR/DataLayout.h" @@ -36,6 +36,8 @@ #include "llvm/Target/TargetSubtargetInfo.h" using namespace llvm; +#define DEBUG_TYPE "asm-printer" + namespace { struct SrcMgrDiagInfo { const MDNode *LocInfo; @@ -88,7 +90,7 @@ void AsmPrinter::EmitInlineAsm(StringRef Str, const MDNode *LocMDNode, if (!MCAI->useIntegratedAssembler() && !OutStreamer.isIntegratedAssemblerRequired()) { OutStreamer.EmitRawText(Str); - emitInlineAsmEnd(TM.getSubtarget<MCSubtargetInfo>(), 0); + emitInlineAsmEnd(TM.getSubtarget<MCSubtargetInfo>(), nullptr); return; } @@ -98,7 +100,7 @@ void AsmPrinter::EmitInlineAsm(StringRef Str, const MDNode *LocMDNode, // If the current LLVMContext has an inline asm handler, set it in SourceMgr. LLVMContext &LLVMCtx = MMI->getModule()->getContext(); bool HasDiagHandler = false; - if (LLVMCtx.getInlineAsmDiagnosticHandler() != 0) { + if (LLVMCtx.getInlineAsmDiagnosticHandler() != nullptr) { // If the source manager has an issue, we arrange for srcMgrDiagHandler // to be invoked, getting DiagInfo passed into it. DiagInfo.LocInfo = LocMDNode; @@ -134,8 +136,11 @@ void AsmPrinter::EmitInlineAsm(StringRef Str, const MDNode *LocMDNode, // emitInlineAsmEnd(). MCSubtargetInfo STIOrig = *STI; + MCTargetOptions MCOptions; + if (MF) + MCOptions = MF->getTarget().Options.MCOptions; std::unique_ptr<MCTargetAsmParser> TAP( - TM.getTarget().createMCAsmParser(*STI, *Parser, *MII)); + TM.getTarget().createMCAsmParser(*STI, *Parser, *MII, MCOptions)); if (!TAP) report_fatal_error("Inline asm not supported by this streamer because" " we don't have an asm parser for this target\n"); @@ -229,10 +234,10 @@ static void EmitMSInlineAsmStr(const char *AsmStr, const MachineInstr *MI, if (InlineAsm::isMemKind(OpFlags)) { Error = AP->PrintAsmMemoryOperand(MI, OpNo, InlineAsmVariant, - /*Modifier*/ 0, OS); + /*Modifier*/ nullptr, OS); } else { Error = AP->PrintAsmOperand(MI, OpNo, InlineAsmVariant, - /*Modifier*/ 0, OS); + /*Modifier*/ nullptr, OS); } } if (Error) { @@ -324,7 +329,7 @@ static void EmitGCCInlineAsmStr(const char *AsmStr, const MachineInstr *MI, ++LastEmitted; const char *StrStart = LastEmitted; const char *StrEnd = strchr(StrStart, '}'); - if (StrEnd == 0) + if (!StrEnd) report_fatal_error("Unterminated ${:foo} operand in inline asm" " string: '" + Twine(AsmStr) + "'"); @@ -399,11 +404,11 @@ static void EmitGCCInlineAsmStr(const char *AsmStr, const MachineInstr *MI, else { if (InlineAsm::isMemKind(OpFlags)) { Error = AP->PrintAsmMemoryOperand(MI, OpNo, InlineAsmVariant, - Modifier[0] ? Modifier : 0, + Modifier[0] ? Modifier : nullptr, OS); } else { Error = AP->PrintAsmOperand(MI, OpNo, InlineAsmVariant, - Modifier[0] ? Modifier : 0, OS); + Modifier[0] ? Modifier : nullptr, OS); } } } @@ -452,7 +457,7 @@ void AsmPrinter::EmitInlineAsm(const MachineInstr *MI) const { // Get the !srcloc metadata node if we have it, and decode the loc cookie from // it. unsigned LocCookie = 0; - const MDNode *LocMD = 0; + const MDNode *LocMD = nullptr; for (unsigned i = MI->getNumOperands(); i != 0; --i) { if (MI->getOperand(i-1).isMetadata() && (LocMD = MI->getOperand(i-1).getMetadata()) && diff --git a/lib/CodeGen/AsmPrinter/CMakeLists.txt b/lib/CodeGen/AsmPrinter/CMakeLists.txt index b3eddac..b4ef185 100644 --- a/lib/CodeGen/AsmPrinter/CMakeLists.txt +++ b/lib/CodeGen/AsmPrinter/CMakeLists.txt @@ -1,14 +1,18 @@ add_llvm_library(LLVMAsmPrinter + AddressPool.cpp ARMException.cpp AsmPrinter.cpp AsmPrinterDwarf.cpp AsmPrinterInlineAsm.cpp + DbgValueHistoryCalculator.cpp DIE.cpp DIEHash.cpp DwarfAccelTable.cpp DwarfCFIException.cpp DwarfDebug.cpp DwarfException.cpp + DwarfFile.cpp + DwarfStringPool.cpp DwarfUnit.cpp ErlangGCPrinter.cpp OcamlGCPrinter.cpp diff --git a/lib/CodeGen/AsmPrinter/DIE.cpp b/lib/CodeGen/AsmPrinter/DIE.cpp index 26e8f2d..c3dcd9c 100644 --- a/lib/CodeGen/AsmPrinter/DIE.cpp +++ b/lib/CodeGen/AsmPrinter/DIE.cpp @@ -104,15 +104,6 @@ void DIEAbbrev::print(raw_ostream &O) { void DIEAbbrev::dump() { print(dbgs()); } #endif -//===----------------------------------------------------------------------===// -// DIE Implementation -//===----------------------------------------------------------------------===// - -DIE::~DIE() { - for (unsigned i = 0, N = Children.size(); i < N; ++i) - delete Children[i]; -} - /// Climb up the parent chain to get the unit DIE to which this DIE /// belongs. const DIE *DIE::getUnit() const { @@ -131,7 +122,7 @@ const DIE *DIE::getUnitOrNull() const { return p; p = p->getParent(); } - return NULL; + return nullptr; } DIEValue *DIE::findAttribute(dwarf::Attribute Attribute) const { @@ -143,7 +134,7 @@ DIEValue *DIE::findAttribute(dwarf::Attribute Attribute) const { for (size_t i = 0; i < Values.size(); ++i) if (Abbrevs.getData()[i].getAttribute() == Attribute) return Values[i]; - return NULL; + return nullptr; } #ifndef NDEBUG @@ -385,12 +376,12 @@ void DIEEntry::EmitValue(AsmPrinter *AP, dwarf::Form Form) const { if (Form == dwarf::DW_FORM_ref_addr) { const DwarfDebug *DD = AP->getDwarfDebug(); - unsigned Addr = Entry->getOffset(); + 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()); + DwarfCompileUnit *CU = DD->lookupUnit(Entry.getUnit()); assert(CU && "CUDie should belong to a CU."); Addr += CU->getDebugInfoOffset(); if (AP->MAI->doesDwarfUseRelocationsAcrossSections()) @@ -401,7 +392,7 @@ void DIEEntry::EmitValue(AsmPrinter *AP, dwarf::Form Form) const { CU->getSectionSym(), DIEEntry::getRefAddrSize(AP)); } else - AP->EmitInt32(Entry->getOffset()); + AP->EmitInt32(Entry.getOffset()); } unsigned DIEEntry::getRefAddrSize(AsmPrinter *AP) { @@ -418,7 +409,7 @@ unsigned DIEEntry::getRefAddrSize(AsmPrinter *AP) { #ifndef NDEBUG void DIEEntry::print(raw_ostream &O) const { - O << format("Die: 0x%lx", (long)(intptr_t)Entry); + O << format("Die: 0x%lx", (long)(intptr_t)&Entry); } #endif diff --git a/lib/CodeGen/AsmPrinter/DIE.h b/lib/CodeGen/AsmPrinter/DIE.h index 7fefd4f..ef05f17 100644 --- a/lib/CodeGen/AsmPrinter/DIE.h +++ b/lib/CodeGen/AsmPrinter/DIE.h @@ -124,7 +124,13 @@ protected: /// Children DIEs. /// - std::vector<DIE *> Children; + // This can't be a vector<DIE> because pointer validity is requirent for the + // Parent pointer and DIEEntry. + // It can't be a list<DIE> because some clients need pointer validity before + // the object has been added to any child list + // (eg: DwarfUnit::constructVariableDIE). These aren't insurmountable, but may + // be more convoluted than beneficial. + std::vector<std::unique_ptr<DIE>> Children; DIE *Parent; @@ -132,11 +138,15 @@ protected: /// SmallVector<DIEValue *, 12> Values; +protected: + DIE() + : Offset(0), Size(0), Abbrev((dwarf::Tag)0, dwarf::DW_CHILDREN_no), + Parent(nullptr) {} + public: - explicit DIE(unsigned Tag) + explicit DIE(dwarf::Tag Tag) : Offset(0), Size(0), Abbrev((dwarf::Tag)Tag, dwarf::DW_CHILDREN_no), - Parent(0) {} - ~DIE(); + Parent(nullptr) {} // Accessors. DIEAbbrev &getAbbrev() { return Abbrev; } @@ -145,7 +155,9 @@ public: 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 std::vector<std::unique_ptr<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 @@ -166,11 +178,11 @@ public: /// addChild - Add a child to the DIE. /// - void addChild(DIE *Child) { + void addChild(std::unique_ptr<DIE> Child) { assert(!Child->getParent()); Abbrev.setChildrenFlag(dwarf::DW_CHILDREN_yes); - Children.push_back(Child); Child->Parent = this; + Children.push_back(std::move(Child)); } /// findAttribute - Find a value in the DIE with the attribute given, @@ -399,14 +411,13 @@ public: /// 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; + DIE &Entry; public: - explicit DIEEntry(DIE *E) : DIEValue(isEntry), Entry(E) { - assert(E && "Cannot construct a DIEEntry with a null DIE"); + explicit DIEEntry(DIE &E) : DIEValue(isEntry), Entry(E) { } - DIE *getEntry() const { return Entry; } + DIE &getEntry() const { return Entry; } /// EmitValue - Emit debug information entry offset. /// @@ -464,7 +475,7 @@ public: class DIELoc : public DIEValue, public DIE { mutable unsigned Size; // Size in bytes excluding size header. public: - DIELoc() : DIEValue(isLoc), DIE(0), Size(0) {} + DIELoc() : DIEValue(isLoc), Size(0) {} /// ComputeSize - Calculate the size of the location expression. /// @@ -507,7 +518,7 @@ public: class DIEBlock : public DIEValue, public DIE { mutable unsigned Size; // Size in bytes excluding size header. public: - DIEBlock() : DIEValue(isBlock), DIE(0), Size(0) {} + DIEBlock() : DIEValue(isBlock), Size(0) {} /// ComputeSize - Calculate the size of the location expression. /// diff --git a/lib/CodeGen/AsmPrinter/DIEHash.cpp b/lib/CodeGen/AsmPrinter/DIEHash.cpp index 74beec1..c2fad59 100644 --- a/lib/CodeGen/AsmPrinter/DIEHash.cpp +++ b/lib/CodeGen/AsmPrinter/DIEHash.cpp @@ -11,8 +11,6 @@ // //===----------------------------------------------------------------------===// -#define DEBUG_TYPE "dwarfdebug" - #include "ByteStreamer.h" #include "DIEHash.h" #include "DIE.h" @@ -28,6 +26,8 @@ using namespace llvm; +#define DEBUG_TYPE "dwarfdebug" + /// \brief Grabs the string in whichever attribute is passed in and returns /// a reference to it. static StringRef getDIEStringAttr(const DIE &Die, uint16_t Attr) { @@ -309,7 +309,7 @@ void DIEHash::hashAttribute(AttrEntry Attr, dwarf::Tag Tag) { // ... An attribute that refers to another type entry T is processed as // follows: case DIEValue::isEntry: - hashDIEEntry(Attribute, Tag, *cast<DIEEntry>(Value)->getEntry()); + hashDIEEntry(Attribute, Tag, cast<DIEEntry>(Value)->getEntry()); break; case DIEValue::isInteger: { addULEB128('A'); @@ -463,20 +463,18 @@ void DIEHash::computeHash(const DIE &Die) { addAttributes(Die); // Then hash each of the children of the DIE. - for (std::vector<DIE *>::const_iterator I = Die.getChildren().begin(), - E = Die.getChildren().end(); - I != E; ++I) { + for (auto &C : Die.getChildren()) { // 7.27 Step 7 // If C is a nested type entry or a member function entry, ... - if (isType((*I)->getTag()) || (*I)->getTag() == dwarf::DW_TAG_subprogram) { - StringRef Name = getDIEStringAttr(**I, dwarf::DW_AT_name); + if (isType(C->getTag()) || C->getTag() == dwarf::DW_TAG_subprogram) { + StringRef Name = getDIEStringAttr(*C, dwarf::DW_AT_name); // ... and has a DW_AT_name attribute if (!Name.empty()) { - hashNestedType(**I, Name); + hashNestedType(*C, Name); continue; } } - computeHash(**I); + computeHash(*C); } // Following the last (or if there are no children), append a zero byte. diff --git a/lib/CodeGen/AsmPrinter/DIEHash.h b/lib/CodeGen/AsmPrinter/DIEHash.h index 48f1601..175d660 100644 --- a/lib/CodeGen/AsmPrinter/DIEHash.h +++ b/lib/CodeGen/AsmPrinter/DIEHash.h @@ -89,7 +89,7 @@ class DIEHash { }; public: - DIEHash(AsmPrinter *A = NULL) : AP(A) {} + DIEHash(AsmPrinter *A = nullptr) : AP(A) {} /// \brief Computes the ODR signature. uint64_t computeDIEODRSignature(const DIE &Die); diff --git a/lib/CodeGen/AsmPrinter/DbgValueHistoryCalculator.cpp b/lib/CodeGen/AsmPrinter/DbgValueHistoryCalculator.cpp new file mode 100644 index 0000000..6103254 --- /dev/null +++ b/lib/CodeGen/AsmPrinter/DbgValueHistoryCalculator.cpp @@ -0,0 +1,175 @@ +//===-- llvm/CodeGen/AsmPrinter/DbgValueHistoryCalculator.cpp -------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "DbgValueHistoryCalculator.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/Support/Debug.h" +#include "llvm/Target/TargetRegisterInfo.h" +#include <algorithm> +#include <map> + +#define DEBUG_TYPE "dwarfdebug" + +namespace llvm { + +// \brief If @MI is a DBG_VALUE with debug value described by a +// defined register, returns the number of this register. +// In the other case, returns 0. +static unsigned isDescribedByReg(const MachineInstr &MI) { + assert(MI.isDebugValue()); + assert(MI.getNumOperands() == 3); + // If location of variable is described using a register (directly or + // indirecltly), this register is always a first operand. + return MI.getOperand(0).isReg() ? MI.getOperand(0).getReg() : 0; +} + +void DbgValueHistoryMap::startInstrRange(const MDNode *Var, + const MachineInstr &MI) { + // Instruction range should start with a DBG_VALUE instruction for the + // variable. + assert(MI.isDebugValue() && MI.getDebugVariable() == Var); + auto &Ranges = VarInstrRanges[Var]; + if (!Ranges.empty() && Ranges.back().second == nullptr && + Ranges.back().first->isIdenticalTo(&MI)) { + DEBUG(dbgs() << "Coalescing identical DBG_VALUE entries:\n" + << "\t" << Ranges.back().first << "\t" << MI << "\n"); + return; + } + Ranges.push_back(std::make_pair(&MI, nullptr)); +} + +void DbgValueHistoryMap::endInstrRange(const MDNode *Var, + const MachineInstr &MI) { + auto &Ranges = VarInstrRanges[Var]; + // Verify that the current instruction range is not yet closed. + assert(!Ranges.empty() && Ranges.back().second == nullptr); + // For now, instruction ranges are not allowed to cross basic block + // boundaries. + assert(Ranges.back().first->getParent() == MI.getParent()); + Ranges.back().second = &MI; +} + +unsigned DbgValueHistoryMap::getRegisterForVar(const MDNode *Var) const { + const auto &I = VarInstrRanges.find(Var); + if (I == VarInstrRanges.end()) + return 0; + const auto &Ranges = I->second; + if (Ranges.empty() || Ranges.back().second != nullptr) + return 0; + return isDescribedByReg(*Ranges.back().first); +} + +namespace { +// Maps physreg numbers to the variables they describe. +typedef std::map<unsigned, SmallVector<const MDNode *, 1>> RegDescribedVarsMap; +} + +// \brief Claim that @Var is not described by @RegNo anymore. +static void dropRegDescribedVar(RegDescribedVarsMap &RegVars, + unsigned RegNo, const MDNode *Var) { + const auto &I = RegVars.find(RegNo); + assert(RegNo != 0U && I != RegVars.end()); + auto &VarSet = I->second; + const auto &VarPos = std::find(VarSet.begin(), VarSet.end(), Var); + assert(VarPos != VarSet.end()); + VarSet.erase(VarPos); + // Don't keep empty sets in a map to keep it as small as possible. + if (VarSet.empty()) + RegVars.erase(I); +} + +// \brief Claim that @Var is now described by @RegNo. +static void addRegDescribedVar(RegDescribedVarsMap &RegVars, + unsigned RegNo, const MDNode *Var) { + assert(RegNo != 0U); + auto &VarSet = RegVars[RegNo]; + assert(std::find(VarSet.begin(), VarSet.end(), Var) == VarSet.end()); + VarSet.push_back(Var); +} + +// \brief Terminate the location range for variables described by register +// @RegNo by inserting @ClobberingInstr to their history. +static void clobberRegisterUses(RegDescribedVarsMap &RegVars, unsigned RegNo, + DbgValueHistoryMap &HistMap, + const MachineInstr &ClobberingInstr) { + const auto &I = RegVars.find(RegNo); + if (I == RegVars.end()) + return; + // Iterate over all variables described by this register and add this + // instruction to their history, clobbering it. + for (const auto &Var : I->second) + HistMap.endInstrRange(Var, ClobberingInstr); + RegVars.erase(I); +} + +// \brief Terminate location ranges for all variables, described by registers +// clobbered by @MI. +static void clobberRegisterUses(RegDescribedVarsMap &RegVars, + const MachineInstr &MI, + const TargetRegisterInfo *TRI, + DbgValueHistoryMap &HistMap) { + for (const MachineOperand &MO : MI.operands()) { + if (!MO.isReg() || !MO.isDef() || !MO.getReg()) + continue; + for (MCRegAliasIterator AI(MO.getReg(), TRI, true); AI.isValid(); + ++AI) { + unsigned RegNo = *AI; + clobberRegisterUses(RegVars, RegNo, HistMap, MI); + } + } +} + +// \brief Terminate the location range for all register-described variables +// by inserting @ClobberingInstr to their history. +static void clobberAllRegistersUses(RegDescribedVarsMap &RegVars, + DbgValueHistoryMap &HistMap, + const MachineInstr &ClobberingInstr) { + for (const auto &I : RegVars) + for (const auto &Var : I.second) + HistMap.endInstrRange(Var, ClobberingInstr); + RegVars.clear(); +} + +void calculateDbgValueHistory(const MachineFunction *MF, + const TargetRegisterInfo *TRI, + DbgValueHistoryMap &Result) { + RegDescribedVarsMap RegVars; + + for (const auto &MBB : *MF) { + for (const auto &MI : MBB) { + if (!MI.isDebugValue()) { + // Not a DBG_VALUE instruction. It may clobber registers which describe + // some variables. + clobberRegisterUses(RegVars, MI, TRI, Result); + continue; + } + + assert(MI.getNumOperands() > 1 && "Invalid DBG_VALUE instruction!"); + const MDNode *Var = MI.getDebugVariable(); + + if (unsigned PrevReg = Result.getRegisterForVar(Var)) + dropRegDescribedVar(RegVars, PrevReg, Var); + + Result.startInstrRange(Var, MI); + + if (unsigned NewReg = isDescribedByReg(MI)) + addRegDescribedVar(RegVars, NewReg, Var); + } + + // Make sure locations for register-described variables are valid only + // until the end of the basic block (unless it's the last basic block, in + // which case let their liveness run off to the end of the function). + if (!MBB.empty() && &MBB != &MF->back()) + clobberAllRegistersUses(RegVars, Result, MBB.back()); + } +} + +} diff --git a/lib/CodeGen/AsmPrinter/DbgValueHistoryCalculator.h b/lib/CodeGen/AsmPrinter/DbgValueHistoryCalculator.h new file mode 100644 index 0000000..b9177f0 --- /dev/null +++ b/lib/CodeGen/AsmPrinter/DbgValueHistoryCalculator.h @@ -0,0 +1,54 @@ +//===-- llvm/CodeGen/AsmPrinter/DbgValueHistoryCalculator.h ----*- C++ -*--===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef CODEGEN_ASMPRINTER_DBGVALUEHISTORYCALCULATOR_H_ +#define CODEGEN_ASMPRINTER_DBGVALUEHISTORYCALCULATOR_H_ + +#include "llvm/ADT/MapVector.h" +#include "llvm/ADT/SmallVector.h" + +namespace llvm { + +class MachineFunction; +class MachineInstr; +class MDNode; +class TargetRegisterInfo; + +// For each user variable, keep a list of instruction ranges where this variable +// is accessible. The variables are listed in order of appearance. +class DbgValueHistoryMap { + // Each instruction range starts with a DBG_VALUE instruction, specifying the + // location of a variable, which is assumed to be valid until the end of the + // range. If end is not specified, location is valid until the start + // instruction of the next instruction range, or until the end of the + // function. + typedef std::pair<const MachineInstr *, const MachineInstr *> InstrRange; + typedef SmallVector<InstrRange, 4> InstrRanges; + typedef MapVector<const MDNode *, InstrRanges> InstrRangesMap; + InstrRangesMap VarInstrRanges; + +public: + void startInstrRange(const MDNode *Var, const MachineInstr &MI); + void endInstrRange(const MDNode *Var, const MachineInstr &MI); + // Returns register currently describing @Var. If @Var is currently + // unaccessible or is not described by a register, returns 0. + unsigned getRegisterForVar(const MDNode *Var) const; + + bool empty() const { return VarInstrRanges.empty(); } + void clear() { VarInstrRanges.clear(); } + InstrRangesMap::const_iterator begin() const { return VarInstrRanges.begin(); } + InstrRangesMap::const_iterator end() const { return VarInstrRanges.end(); } +}; + +void calculateDbgValueHistory(const MachineFunction *MF, + const TargetRegisterInfo *TRI, + DbgValueHistoryMap &Result); +} + +#endif diff --git a/lib/CodeGen/AsmPrinter/DebugLocEntry.h b/lib/CodeGen/AsmPrinter/DebugLocEntry.h index 470453f..3beb799 100644 --- a/lib/CodeGen/AsmPrinter/DebugLocEntry.h +++ b/lib/CodeGen/AsmPrinter/DebugLocEntry.h @@ -23,75 +23,82 @@ class DebugLocEntry { 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; +public: + /// A single location or constant. + struct Value { + Value(const MDNode *Var, int64_t i) + : Variable(Var), EntryKind(E_Integer) { + Constant.Int = i; + } + Value(const MDNode *Var, const ConstantFP *CFP) + : Variable(Var), EntryKind(E_ConstantFP) { + Constant.CFP = CFP; + } + Value(const MDNode *Var, const ConstantInt *CIP) + : Variable(Var), EntryKind(E_ConstantInt) { + Constant.CIP = CIP; + } + Value(const MDNode *Var, MachineLocation Loc) + : Variable(Var), EntryKind(E_Location), Loc(Loc) { + } - union { - int64_t Int; - const ConstantFP *CFP; - const ConstantInt *CIP; - } Constants; + // The variable to which this location entry corresponds. + const MDNode *Variable; - // The location in the machine frame. - MachineLocation Loc; + // Type of entry that this represents. + enum EntryType { E_Location, E_Integer, E_ConstantFP, E_ConstantInt }; + enum EntryType EntryKind; - // The variable to which this location entry corresponds. - const MDNode *Variable; + // Either a constant, + union { + int64_t Int; + const ConstantFP *CFP; + const ConstantInt *CIP; + } Constant; - // The compile unit to which this location entry is referenced by. - const DwarfCompileUnit *Unit; + // Or a location in the machine frame. + MachineLocation Loc; - bool hasSameValueOrLocation(const DebugLocEntry &Next) { - if (EntryKind != Next.EntryKind) - return false; + bool operator==(const Value &other) const { + if (EntryKind != other.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; + switch (EntryKind) { + case E_Location: + return Loc == other.Loc; + case E_Integer: + return Constant.Int == other.Constant.Int; + case E_ConstantFP: + return Constant.CFP == other.Constant.CFP; + case E_ConstantInt: + return Constant.CIP == other.Constant.CIP; + } + llvm_unreachable("unhandled EntryKind"); } - return EqualValues; - } + bool isLocation() const { return EntryKind == E_Location; } + bool isInt() const { return EntryKind == E_Integer; } + bool isConstantFP() const { return EntryKind == E_ConstantFP; } + bool isConstantInt() const { return EntryKind == E_ConstantInt; } + int64_t getInt() const { return Constant.Int; } + const ConstantFP *getConstantFP() const { return Constant.CFP; } + const ConstantInt *getConstantInt() const { return Constant.CIP; } + MachineLocation getLoc() const { return Loc; } + const MDNode *getVariable() const { return Variable; } + }; +private: + /// A list of locations/constants belonging to this entry. + SmallVector<Value, 1> Values; + + /// The compile unit that this location entry is referenced by. + const DwarfCompileUnit *Unit; 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; + DebugLocEntry() : Begin(nullptr), End(nullptr), Unit(nullptr) {} + DebugLocEntry(const MCSymbol *B, const MCSymbol *E, + Value Val, const DwarfCompileUnit *U) + : Begin(B), End(E), Unit(U) { + Values.push_back(std::move(Val)); } /// \brief Attempt to merge this DebugLocEntry with Next and return @@ -99,24 +106,17 @@ public: /// share the same Loc/Constant and if Next immediately follows this /// Entry. bool Merge(const DebugLocEntry &Next) { - if (End == Next.Begin && hasSameValueOrLocation(Next)) { + if ((End == Next.Begin && Values == Next.Values)) { 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; } + const ArrayRef<Value> getValues() const { return Values; } + void addValue(Value Val) { Values.push_back(Val); } }; } diff --git a/lib/CodeGen/AsmPrinter/DwarfAccelTable.cpp b/lib/CodeGen/AsmPrinter/DwarfAccelTable.cpp index bcbb6c8..e9527c4 100644 --- a/lib/CodeGen/AsmPrinter/DwarfAccelTable.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfAccelTable.cpp @@ -29,14 +29,15 @@ DwarfAccelTable::DwarfAccelTable(ArrayRef<DwarfAccelTable::Atom> atomList) : Header(8 + (atomList.size() * 4)), HeaderData(atomList), Entries(Allocator) {} -DwarfAccelTable::~DwarfAccelTable() {} - -void DwarfAccelTable::AddName(StringRef Name, const DIE *die, char Flags) { +void DwarfAccelTable::AddName(StringRef Name, MCSymbol *StrSym, const DIE *die, + char Flags) { assert(Data.empty() && "Already finalized!"); // If the string is in the list already then add this die to the list // otherwise add a new one. DataArray &DIEs = Entries[Name]; - DIEs.push_back(new (Allocator) HashDataContents(die, Flags)); + assert(!DIEs.StrSym || DIEs.StrSym == StrSym); + DIEs.StrSym = StrSym; + DIEs.Values.push_back(new (Allocator) HashDataContents(die, Flags)); } void DwarfAccelTable::ComputeBucketCount(void) { @@ -72,9 +73,10 @@ void DwarfAccelTable::FinalizeTable(AsmPrinter *Asm, StringRef Prefix) { EI != EE; ++EI) { // Unique the entries. - std::stable_sort(EI->second.begin(), EI->second.end(), compareDIEs); - EI->second.erase(std::unique(EI->second.begin(), EI->second.end()), - EI->second.end()); + std::stable_sort(EI->second.Values.begin(), EI->second.Values.end(), compareDIEs); + EI->second.Values.erase( + std::unique(EI->second.Values.begin(), EI->second.Values.end()), + EI->second.Values.end()); HashData *Entry = new (Allocator) HashData(EI->getKey(), EI->second); Data.push_back(Entry); @@ -181,21 +183,18 @@ void DwarfAccelTable::EmitData(AsmPrinter *Asm, DwarfFile *D) { // Remember to emit the label for our offset. Asm->OutStreamer.EmitLabel((*HI)->Sym); Asm->OutStreamer.AddComment((*HI)->Str); - Asm->EmitSectionOffset(D->getStringPoolEntry((*HI)->Str), - D->getStringPoolSym()); + Asm->EmitSectionOffset((*HI)->Data.StrSym, + D->getStringPool().getSectionSymbol()); Asm->OutStreamer.AddComment("Num DIEs"); - Asm->EmitInt32((*HI)->Data.size()); - for (ArrayRef<HashDataContents *>::const_iterator - DI = (*HI)->Data.begin(), - DE = (*HI)->Data.end(); - DI != DE; ++DI) { + Asm->EmitInt32((*HI)->Data.Values.size()); + for (HashDataContents *HD : (*HI)->Data.Values) { // Emit the DIE offset - Asm->EmitInt32((*DI)->Die->getOffset()); + Asm->EmitInt32(HD->Die->getOffset()); // If we have multiple Atoms emit that info too. // FIXME: A bit of a hack, we either emit only one atom or all info. if (HeaderData.Atoms.size() > 1) { - Asm->EmitInt16((*DI)->Die->getTag()); - Asm->EmitInt8((*DI)->Flags); + Asm->EmitInt16(HD->Die->getTag()); + Asm->EmitInt8(HD->Flags); } } // Emit a 0 to terminate the data unless we have a hash collision. @@ -235,10 +234,8 @@ void DwarfAccelTable::print(raw_ostream &O) { EE = Entries.end(); EI != EE; ++EI) { O << "Name: " << EI->getKeyData() << "\n"; - for (DataArray::const_iterator DI = EI->second.begin(), - DE = EI->second.end(); - DI != DE; ++DI) - (*DI)->print(O); + for (HashDataContents *HD : EI->second.Values) + HD->print(O); } O << "Buckets and Hashes: \n"; diff --git a/lib/CodeGen/AsmPrinter/DwarfAccelTable.h b/lib/CodeGen/AsmPrinter/DwarfAccelTable.h index 4a14497..a3cc95f 100644 --- a/lib/CodeGen/AsmPrinter/DwarfAccelTable.h +++ b/lib/CodeGen/AsmPrinter/DwarfAccelTable.h @@ -18,6 +18,7 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringMap.h" #include "llvm/MC/MCSymbol.h" +#include "llvm/Support/Compiler.h" #include "llvm/Support/DataTypes.h" #include "llvm/Support/Debug.h" #include "llvm/Support/Dwarf.h" @@ -125,7 +126,8 @@ public: uint16_t type; // enum AtomType uint16_t form; // DWARF DW_FORM_ defines - Atom(uint16_t type, uint16_t form) : type(type), form(form) {} + LLVM_CONSTEXPR Atom(uint16_t type, uint16_t form) + : type(type), form(form) {} #ifndef NDEBUG void print(raw_ostream &O) { O << "Type: " << dwarf::AtomTypeString(type) << "\n" @@ -177,12 +179,19 @@ public: }; private: + // String Data + struct DataArray { + MCSymbol *StrSym; + std::vector<HashDataContents *> Values; + DataArray() : StrSym(nullptr) {} + }; + friend struct HashData; struct HashData { StringRef Str; uint32_t HashValue; MCSymbol *Sym; - ArrayRef<HashDataContents *> Data; // offsets - HashData(StringRef S, ArrayRef<HashDataContents *> Data) + DwarfAccelTable::DataArray &Data; // offsets + HashData(StringRef S, DwarfAccelTable::DataArray &Data) : Str(S), Data(Data) { HashValue = DwarfAccelTable::HashDJB(S); } @@ -196,10 +205,10 @@ private: else O << "<none>"; O << "\n"; - for (size_t i = 0; i < Data.size(); i++) { - O << " Offset: " << Data[i]->Die->getOffset() << "\n"; - O << " Tag: " << dwarf::TagString(Data[i]->Die->getTag()) << "\n"; - O << " Flags: " << Data[i]->Flags << "\n"; + for (HashDataContents *C : Data.Values) { + O << " Offset: " << C->Die->getOffset() << "\n"; + O << " Tag: " << dwarf::TagString(C->Die->getTag()) << "\n"; + O << " Flags: " << C->Flags << "\n"; } } void dump() { print(dbgs()); } @@ -224,8 +233,6 @@ private: TableHeaderData HeaderData; std::vector<HashData *> Data; - // String Data - typedef std::vector<HashDataContents *> DataArray; typedef StringMap<DataArray, BumpPtrAllocator &> StringEntries; StringEntries Entries; @@ -238,8 +245,8 @@ private: // Public Implementation public: DwarfAccelTable(ArrayRef<DwarfAccelTable::Atom>); - ~DwarfAccelTable(); - void AddName(StringRef, const DIE *, char = 0); + void AddName(StringRef Name, MCSymbol *StrSym, const DIE *Die, + char Flags = 0); void FinalizeTable(AsmPrinter *, StringRef); void Emit(AsmPrinter *, MCSymbol *, DwarfFile *); #ifndef NDEBUG diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp index 11345eb..2a0615d 100644 --- a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -11,12 +11,10 @@ // //===----------------------------------------------------------------------===// -#define DEBUG_TYPE "dwarfdebug" #include "ByteStreamer.h" #include "DwarfDebug.h" #include "DIE.h" #include "DIEHash.h" -#include "DwarfAccelTable.h" #include "DwarfUnit.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/Statistic.h" @@ -51,6 +49,8 @@ #include "llvm/Target/TargetRegisterInfo.h" using namespace llvm; +#define DEBUG_TYPE "dwarfdebug" + static cl::opt<bool> DisableDebugInfoPrinting("disable-debug-info-print", cl::Hidden, cl::desc("Disable debug info printing")); @@ -107,8 +107,6 @@ static const char *const DbgTimerName = "DWARF Debug Writer"; //===----------------------------------------------------------------------===// -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 { @@ -120,7 +118,6 @@ bool DbgVariable::isBlockByrefVariable() const { return Var.isBlockByrefVariable(DD->getTypeIdentifierMap()); } - DIType DbgVariable::getType() const { DIType Ty = Var.getType().resolve(DD->getTypeIdentifierMap()); // FIXME: isBlockByrefVariable should be reformulated in terms of complex @@ -166,29 +163,32 @@ DIType DbgVariable::getType() const { return Ty; } -} // end llvm namespace - -/// Return Dwarf Version by checking module flags. -static unsigned getDwarfVersionFromModule(const Module *M) { - Value *Val = M->getModuleFlag("Dwarf Version"); - if (!Val) - return dwarf::DWARF_VERSION; - return cast<ConstantInt>(Val)->getZExtValue(); -} +static LLVM_CONSTEXPR DwarfAccelTable::Atom TypeAtoms[] = { + DwarfAccelTable::Atom(dwarf::DW_ATOM_die_offset, dwarf::DW_FORM_data4), + DwarfAccelTable::Atom(dwarf::DW_ATOM_die_tag, dwarf::DW_FORM_data2), + DwarfAccelTable::Atom(dwarf::DW_ATOM_type_flags, dwarf::DW_FORM_data1)}; DwarfDebug::DwarfDebug(AsmPrinter *A, Module *M) - : Asm(A), MMI(Asm->MMI), FirstCU(0), PrevLabel(NULL), GlobalRangeCount(0), - InfoHolder(A, "info_string", DIEValueAllocator), + : Asm(A), MMI(Asm->MMI), FirstCU(nullptr), PrevLabel(nullptr), + 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; + SkeletonHolder(A, "skel_string", DIEValueAllocator), + AccelNames(DwarfAccelTable::Atom(dwarf::DW_ATOM_die_offset, + dwarf::DW_FORM_data4)), + AccelObjC(DwarfAccelTable::Atom(dwarf::DW_ATOM_die_offset, + dwarf::DW_FORM_data4)), + AccelNamespace(DwarfAccelTable::Atom(dwarf::DW_ATOM_die_offset, + dwarf::DW_FORM_data4)), + AccelTypes(TypeAtoms) { + + DwarfInfoSectionSym = DwarfAbbrevSectionSym = DwarfStrSectionSym = nullptr; + DwarfDebugRangeSectionSym = DwarfDebugLocSectionSym = nullptr; + DwarfLineSectionSym = nullptr; + DwarfAddrSectionSym = nullptr; + DwarfAbbrevDWOSectionSym = DwarfStrDWOSectionSym = nullptr; + FunctionBeginSym = FunctionEndSym = nullptr; + CurFn = nullptr; + CurMI = nullptr; // Turn on accelerator tables for Darwin by default, pubnames by // default for non-Darwin, and handle split dwarf. @@ -209,9 +209,8 @@ DwarfDebug::DwarfDebug(AsmPrinter *A, Module *M) else HasDwarfPubSections = DwarfPubSections == Enable; - DwarfVersion = DwarfVersionNumber - ? DwarfVersionNumber - : getDwarfVersionFromModule(MMI->getModule()); + DwarfVersion = DwarfVersionNumber ? DwarfVersionNumber + : MMI->getModule()->getDwarfVersion(); { NamedRegionTimer T(DbgTimerName, DWARFGroupName, TimePassesIsEnabled); @@ -219,76 +218,22 @@ DwarfDebug::DwarfDebug(AsmPrinter *A, Module *M) } } +// Define out of line so we don't have to include DwarfUnit.h in DwarfDebug.h. +DwarfDebug::~DwarfDebug() { } + // Switch to the specified MCSection and emit an assembler // temporary label to it if SymbolStem is specified. static MCSymbol *emitSectionSym(AsmPrinter *Asm, const MCSection *Section, - const char *SymbolStem = 0) { + const char *SymbolStem = nullptr) { Asm->OutStreamer.SwitchSection(Section); if (!SymbolStem) - return 0; + return nullptr; MCSymbol *TmpSym = Asm->GetTempSymbol(SymbolStem); Asm->OutStreamer.EmitLabel(TmpSym); return TmpSym; } -DwarfFile::~DwarfFile() { - for (DwarfUnit *DU : CUs) - delete DU; -} - -MCSymbol *DwarfFile::getStringPoolSym() { - return Asm->GetTempSymbol(StringPref); -} - -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 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 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.Number; -} - -// Define a unique number for the abbreviation. -// -void DwarfFile::assignAbbrevNumber(DIEAbbrev &Abbrev) { - // Check the set for priors. - DIEAbbrev *InSet = AbbreviationsSet.GetOrInsertNode(&Abbrev); - - // If it's newly added. - if (InSet == &Abbrev) { - // Add to abbreviation list. - Abbreviations.push_back(&Abbrev); - - // Assign the vector position + 1 as its number. - Abbrev.setNumber(Abbreviations.size()); - } else { - // Assign existing abbreviation number. - Abbrev.setNumber(InSet->getNumber()); - } -} - static bool isObjCClass(StringRef Name) { return Name.startswith("+") || Name.startswith("-"); } @@ -328,26 +273,26 @@ static bool SectionSort(const MCSection *A, const MCSection *B) { // 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(DwarfUnit *TheU, DISubprogram SP, DIE *Die) { +void DwarfDebug::addSubprogramNames(DISubprogram SP, DIE &Die) { if (!SP.isDefinition()) return; - TheU->addAccelName(SP.getName(), Die); + 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()) - TheU->addAccelName(SP.getLinkageName(), Die); + 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); - TheU->addAccelObjC(Class, Die); + addAccelObjC(Class, Die); if (Category != "") - TheU->addAccelObjC(Category, Die); + addAccelObjC(Category, Die); // Also add the base method name to the name table. - TheU->addAccelName(getObjCMethodName(SP.getName()), Die); + addAccelName(getObjCMethodName(SP.getName()), Die); } } @@ -367,58 +312,21 @@ 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(DwarfCompileUnit *SPCU, +DIE &DwarfDebug::updateSubprogramScopeDIE(DwarfCompileUnit &SPCU, DISubprogram SP) { - DIE *SPDie = SPCU->getDIE(SP); - - assert(SPDie && "Unable to find subprogram DIE!"); - - // If we're updating an abstract DIE, then we will be adding the children and - // object pointer later on. But what we don't want to do is process the - // concrete DIE twice. - if (DIE *AbsSPDIE = AbstractSPDies.lookup(SP)) { - // Pick up abstract subprogram DIE. - SPDie = - SPCU->createAndAddDIE(dwarf::DW_TAG_subprogram, *SPCU->getUnitDie()); - SPCU->addDIEEntry(SPDie, dwarf::DW_AT_abstract_origin, AbsSPDIE); - } else { - DISubprogram SPDecl = SP.getFunctionDeclaration(); - if (!SPDecl.isSubprogram()) { - // There is not any need to generate specification DIE for a function - // defined at compile unit level. If a function is defined inside another - // function then gdb prefers the definition at top level and but does not - // expect specification DIE in parent function. So avoid creating - // specification DIE for a function defined inside a function. - DIScope SPContext = resolve(SP.getContext()); - if (SP.isDefinition() && !SPContext.isCompileUnit() && - !SPContext.isFile() && !isSubprogramContext(SPContext)) { - SPCU->addFlag(SPDie, dwarf::DW_AT_declaration); - - // Add arguments. - DICompositeType SPTy = SP.getType(); - DIArray Args = SPTy.getTypeArray(); - uint16_t SPTag = SPTy.getTag(); - if (SPTag == dwarf::DW_TAG_subroutine_type) - SPCU->constructSubprogramArguments(*SPDie, Args); - DIE *SPDeclDie = SPDie; - SPDie = SPCU->createAndAddDIE(dwarf::DW_TAG_subprogram, - *SPCU->getUnitDie()); - SPCU->addDIEEntry(SPDie, dwarf::DW_AT_specification, SPDeclDie); - } - } - } + DIE *SPDie = SPCU.getOrCreateSubprogramDIE(SP); - attachLowHighPC(SPCU, SPDie, FunctionBeginSym, FunctionEndSym); + 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); + SPCU.addAddress(*SPDie, dwarf::DW_AT_frame_base, Location); // Add name to the name table, we do this here because we're guaranteed // to have concrete versions of our DW_TAG_subprogram nodes. - addSubprogramNames(SPCU, SP, SPDie); + addSubprogramNames(SP, *SPDie); - return SPDie; + return *SPDie; } /// Check whether we should create a DIE for the given Scope, return true @@ -442,16 +350,16 @@ bool DwarfDebug::isLexicalScopeDIENull(LexicalScope *Scope) { return !End; } -static void addSectionLabel(AsmPrinter *Asm, DwarfUnit *U, DIE *D, +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); + if (Asm.MAI->doesDwarfUseRelocationsAcrossSections()) + U.addSectionLabel(D, A, L); else - U->addSectionDelta(D, A, L, Sec); + U.addSectionDelta(D, A, L, Sec); } -void DwarfDebug::addScopeRangeList(DwarfCompileUnit *TheCU, DIE *ScopeDIE, +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. @@ -460,10 +368,10 @@ void DwarfDebug::addScopeRangeList(DwarfCompileUnit *TheCU, DIE *ScopeDIE, // 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); + TheCU.addSectionDelta(ScopeDIE, dwarf::DW_AT_ranges, RangeSym, + DwarfDebugRangeSectionSym); else - addSectionLabel(Asm, TheCU, ScopeDIE, dwarf::DW_AT_ranges, RangeSym, + addSectionLabel(*Asm, TheCU, ScopeDIE, dwarf::DW_AT_ranges, RangeSym, DwarfDebugRangeSectionSym); RangeSpanList List(RangeSym); @@ -473,227 +381,256 @@ void DwarfDebug::addScopeRangeList(DwarfCompileUnit *TheCU, DIE *ScopeDIE, } // Add the range list to the set of ranges to be emitted. - TheCU->addRangeList(std::move(List)); + TheCU.addRangeList(std::move(List)); +} + +void DwarfDebug::attachRangesOrLowHighPC(DwarfCompileUnit &TheCU, DIE &Die, + const SmallVectorImpl<InsnRange> &Ranges) { + assert(!Ranges.empty()); + if (Ranges.size() == 1) + attachLowHighPC(TheCU, Die, getLabelBeforeInsn(Ranges.front().first), + getLabelAfterInsn(Ranges.front().second)); + else + addScopeRangeList(TheCU, Die, Ranges); } // Construct new DW_TAG_lexical_block for this scope and attach // DW_AT_low_pc/DW_AT_high_pc labels. -DIE *DwarfDebug::constructLexicalScopeDIE(DwarfCompileUnit *TheCU, - LexicalScope *Scope) { +std::unique_ptr<DIE> +DwarfDebug::constructLexicalScopeDIE(DwarfCompileUnit &TheCU, + LexicalScope *Scope) { if (isLexicalScopeDIENull(Scope)) - return 0; + return nullptr; - DIE *ScopeDIE = new DIE(dwarf::DW_TAG_lexical_block); + auto ScopeDIE = make_unique<DIE>(dwarf::DW_TAG_lexical_block); if (Scope->isAbstractScope()) return ScopeDIE; - const SmallVectorImpl<InsnRange> &ScopeRanges = Scope->getRanges(); - - // 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 = ScopeRanges.begin(); - MCSymbol *Start = getLabelBeforeInsn(RI->first); - MCSymbol *End = getLabelAfterInsn(RI->second); - assert(End && "End label should not be null!"); - - assert(Start->isDefined() && "Invalid starting label for an inlined scope!"); - assert(End->isDefined() && "Invalid end label for an inlined scope!"); - - attachLowHighPC(TheCU, ScopeDIE, Start, End); + attachRangesOrLowHighPC(TheCU, *ScopeDIE, Scope->getRanges()); return ScopeDIE; } // This scope represents inlined body of a function. Construct DIE to // represent this concrete inlined copy of the function. -DIE *DwarfDebug::constructInlinedScopeDIE(DwarfCompileUnit *TheCU, - LexicalScope *Scope) { - const SmallVectorImpl<InsnRange> &ScopeRanges = Scope->getRanges(); - assert(!ScopeRanges.empty() && - "LexicalScope does not have instruction markers!"); - - if (!Scope->getScopeNode()) - return NULL; +std::unique_ptr<DIE> +DwarfDebug::constructInlinedScopeDIE(DwarfCompileUnit &TheCU, + LexicalScope *Scope) { + assert(Scope->getScopeNode()); DIScope DS(Scope->getScopeNode()); DISubprogram InlinedSP = getDISubprogram(DS); - DIE *OriginDIE = TheCU->getDIE(InlinedSP); - if (!OriginDIE) { - DEBUG(dbgs() << "Unable to find original DIE for an inlined subprogram."); - return NULL; - } - - DIE *ScopeDIE = new DIE(dwarf::DW_TAG_inlined_subroutine); - TheCU->addDIEEntry(ScopeDIE, dwarf::DW_AT_abstract_origin, OriginDIE); + // Find the subprogram's DwarfCompileUnit in the SPMap in case the subprogram + // was inlined from another compile unit. + DIE *OriginDIE = AbstractSPDies[InlinedSP]; + assert(OriginDIE && "Unable to find original DIE for an inlined subprogram."); - // 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); + auto ScopeDIE = make_unique<DIE>(dwarf::DW_TAG_inlined_subroutine); + TheCU.addDIEEntry(*ScopeDIE, dwarf::DW_AT_abstract_origin, *OriginDIE); - if (StartLabel == 0 || EndLabel == 0) - llvm_unreachable("Unexpected Start and End labels for an inlined scope!"); - - assert(StartLabel->isDefined() && - "Invalid starting label for an inlined scope!"); - assert(EndLabel->isDefined() && "Invalid end label for an inlined scope!"); - - attachLowHighPC(TheCU, ScopeDIE, StartLabel, EndLabel); - } + attachRangesOrLowHighPC(TheCU, *ScopeDIE, Scope->getRanges()); InlinedSubprogramDIEs.insert(OriginDIE); // Add the call site information to the DIE. DILocation DL(Scope->getInlinedAt()); - 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()); + 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 // to have concrete versions of our DW_TAG_inlined_subprogram nodes. - addSubprogramNames(TheCU, InlinedSP, ScopeDIE); + addSubprogramNames(InlinedSP, *ScopeDIE); return ScopeDIE; } -DIE *DwarfDebug::createScopeChildrenDIE(DwarfCompileUnit *TheCU, - LexicalScope *Scope, - SmallVectorImpl<DIE *> &Children) { - DIE *ObjectPointer = NULL; +static std::unique_ptr<DIE> constructVariableDIE(DwarfCompileUnit &TheCU, + DbgVariable &DV, + const LexicalScope &Scope, + DIE *&ObjectPointer) { + auto Var = TheCU.constructVariableDIE(DV, Scope.isAbstractScope()); + if (DV.isObjectPointer()) + ObjectPointer = Var.get(); + return Var; +} + +DIE *DwarfDebug::createScopeChildrenDIE( + DwarfCompileUnit &TheCU, LexicalScope *Scope, + SmallVectorImpl<std::unique_ptr<DIE>> &Children) { + DIE *ObjectPointer = nullptr; // Collect arguments for current function. if (LScopes.isCurrentFunctionScope(Scope)) { for (DbgVariable *ArgDV : CurrentFnArguments) if (ArgDV) - if (DIE *Arg = - TheCU->constructVariableDIE(*ArgDV, Scope->isAbstractScope())) { - Children.push_back(Arg); - if (ArgDV->isObjectPointer()) - ObjectPointer = Arg; - } + Children.push_back( + constructVariableDIE(TheCU, *ArgDV, *Scope, ObjectPointer)); // 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); + Children.push_back( + make_unique<DIE>(dwarf::DW_TAG_unspecified_parameters)); } } // Collect lexical scope children first. for (DbgVariable *DV : ScopeVariables.lookup(Scope)) - if (DIE *Variable = TheCU->constructVariableDIE(*DV, - Scope->isAbstractScope())) { - Children.push_back(Variable); - if (DV->isObjectPointer()) - ObjectPointer = Variable; - } + Children.push_back(constructVariableDIE(TheCU, *DV, *Scope, ObjectPointer)); + for (LexicalScope *LS : Scope->getChildren()) - if (DIE *Nested = constructScopeDIE(TheCU, LS)) - Children.push_back(Nested); + if (std::unique_ptr<DIE> Nested = constructScopeDIE(TheCU, LS)) + Children.push_back(std::move(Nested)); return ObjectPointer; } +void DwarfDebug::createAndAddScopeChildren(DwarfCompileUnit &TheCU, + LexicalScope *Scope, DIE &ScopeDIE) { + // We create children when the scope DIE is not null. + SmallVector<std::unique_ptr<DIE>, 8> Children; + if (DIE *ObjectPointer = createScopeChildrenDIE(TheCU, Scope, Children)) + TheCU.addDIEEntry(ScopeDIE, dwarf::DW_AT_object_pointer, *ObjectPointer); + + // Add children + for (auto &I : Children) + ScopeDIE.addChild(std::move(I)); +} + +void DwarfDebug::constructAbstractSubprogramScopeDIE(DwarfCompileUnit &TheCU, + LexicalScope *Scope) { + assert(Scope && Scope->getScopeNode()); + assert(Scope->isAbstractScope()); + assert(!Scope->getInlinedAt()); + + DISubprogram SP(Scope->getScopeNode()); + + ProcessedSPNodes.insert(SP); + + DIE *&AbsDef = AbstractSPDies[SP]; + if (AbsDef) + return; + + // Find the subprogram's DwarfCompileUnit in the SPMap in case the subprogram + // was inlined from another compile unit. + DwarfCompileUnit &SPCU = *SPMap[SP]; + DIE *ContextDIE; + + // Some of this is duplicated from DwarfUnit::getOrCreateSubprogramDIE, with + // the important distinction that the DIDescriptor is not associated with the + // DIE (since the DIDescriptor will be associated with the concrete DIE, if + // any). It could be refactored to some common utility function. + if (DISubprogram SPDecl = SP.getFunctionDeclaration()) { + ContextDIE = &SPCU.getUnitDie(); + SPCU.getOrCreateSubprogramDIE(SPDecl); + } else + ContextDIE = SPCU.getOrCreateContextDIE(resolve(SP.getContext())); + + // Passing null as the associated DIDescriptor because the abstract definition + // shouldn't be found by lookup. + AbsDef = &SPCU.createAndAddDIE(dwarf::DW_TAG_subprogram, *ContextDIE, + DIDescriptor()); + SPCU.applySubprogramAttributes(SP, *AbsDef); + SPCU.addGlobalName(SP.getName(), *AbsDef, resolve(SP.getContext())); + + SPCU.addUInt(*AbsDef, dwarf::DW_AT_inline, None, dwarf::DW_INL_inlined); + createAndAddScopeChildren(SPCU, Scope, *AbsDef); +} + +DIE &DwarfDebug::constructSubprogramScopeDIE(DwarfCompileUnit &TheCU, + LexicalScope *Scope) { + assert(Scope && Scope->getScopeNode()); + assert(!Scope->getInlinedAt()); + assert(!Scope->isAbstractScope()); + DISubprogram Sub(Scope->getScopeNode()); + + assert(Sub.isSubprogram()); + + ProcessedSPNodes.insert(Sub); + + DIE &ScopeDIE = updateSubprogramScopeDIE(TheCU, Sub); + + createAndAddScopeChildren(TheCU, Scope, ScopeDIE); + + return ScopeDIE; +} + // Construct a DIE for this scope. -DIE *DwarfDebug::constructScopeDIE(DwarfCompileUnit *TheCU, - LexicalScope *Scope) { +std::unique_ptr<DIE> DwarfDebug::constructScopeDIE(DwarfCompileUnit &TheCU, + LexicalScope *Scope) { if (!Scope || !Scope->getScopeNode()) - return NULL; + return nullptr; DIScope DS(Scope->getScopeNode()); - SmallVector<DIE *, 8> Children; - DIE *ObjectPointer = NULL; - bool ChildrenCreated = false; + assert((Scope->getInlinedAt() || !DS.isSubprogram()) && + "Only handle inlined subprograms here, use " + "constructSubprogramScopeDIE for non-inlined " + "subprograms"); + + SmallVector<std::unique_ptr<DIE>, 8> Children; // We try to create the scope DIE first, then the children DIEs. This will // avoid creating un-used children then removing them later when we find out // the scope DIE is null. - DIE *ScopeDIE = NULL; - if (Scope->getInlinedAt()) + std::unique_ptr<DIE> ScopeDIE; + if (Scope->getParent() && DS.isSubprogram()) { ScopeDIE = constructInlinedScopeDIE(TheCU, Scope); - else if (DS.isSubprogram()) { - ProcessedSPNodes.insert(DS); - if (Scope->isAbstractScope()) { - ScopeDIE = TheCU->getDIE(DS); - // Note down abstract DIE. - if (ScopeDIE) - AbstractSPDies.insert(std::make_pair(DS, ScopeDIE)); - } else - ScopeDIE = updateSubprogramScopeDIE(TheCU, DISubprogram(DS)); + if (!ScopeDIE) + return nullptr; + // We create children when the scope DIE is not null. + createScopeChildrenDIE(TheCU, Scope, Children); } else { // Early exit when we know the scope DIE is going to be null. if (isLexicalScopeDIENull(Scope)) - return NULL; + return nullptr; // We create children here when we know the scope DIE is not going to be // null and the children will be added to the scope DIE. - ObjectPointer = createScopeChildrenDIE(TheCU, Scope, Children); - ChildrenCreated = true; + createScopeChildrenDIE(TheCU, Scope, Children); // 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()); + std::equal_range(ScopesWithImportedEntities.begin(), + ScopesWithImportedEntities.end(), + std::pair<const MDNode *, const MDNode *>(DS, nullptr), + less_first()); if (Children.empty() && Range.first == Range.second) - return NULL; + return nullptr; ScopeDIE = constructLexicalScopeDIE(TheCU, Scope); assert(ScopeDIE && "Scope DIE should not be null."); for (ImportedEntityMap::const_iterator i = Range.first; i != Range.second; ++i) - constructImportedEntityDIE(TheCU, i->second, ScopeDIE); + constructImportedEntityDIE(TheCU, i->second, *ScopeDIE); } - if (!ScopeDIE) { - assert(Children.empty() && - "We create children only when the scope DIE is not null."); - return NULL; - } - if (!ChildrenCreated) - // We create children when the scope DIE is not null. - ObjectPointer = createScopeChildrenDIE(TheCU, Scope, Children); - // Add children - for (DIE *I : Children) - ScopeDIE->addChild(I); - - if (DS.isSubprogram() && ObjectPointer != NULL) - TheCU->addDIEEntry(ScopeDIE, dwarf::DW_AT_object_pointer, ObjectPointer); + for (auto &I : Children) + ScopeDIE->addChild(std::move(I)); return ScopeDIE; } -void DwarfDebug::addGnuPubAttributes(DwarfUnit *U, DIE *D) const { +void DwarfDebug::addGnuPubAttributes(DwarfUnit &U, DIE &D) const { if (!GenerateGnuPubSections) return; - U->addFlag(D, dwarf::DW_AT_GNU_pubnames); + U.addFlag(D, dwarf::DW_AT_GNU_pubnames); } // Create new DwarfCompileUnit for the given metadata node with tag // DW_TAG_compile_unit. -DwarfCompileUnit *DwarfDebug::constructDwarfCompileUnit(DICompileUnit DIUnit) { +DwarfCompileUnit &DwarfDebug::constructDwarfCompileUnit(DICompileUnit DIUnit) { StringRef FN = DIUnit.getFilename(); CompilationDir = DIUnit.getDirectory(); - DIE *Die = new DIE(dwarf::DW_TAG_compile_unit); - DwarfCompileUnit *NewCU = new DwarfCompileUnit( - InfoHolder.getUnits().size(), Die, DIUnit, Asm, this, &InfoHolder); - InfoHolder.addUnit(NewCU); + auto OwnedUnit = make_unique<DwarfCompileUnit>( + InfoHolder.getUnits().size(), DIUnit, Asm, this, &InfoHolder); + DwarfCompileUnit &NewCU = *OwnedUnit; + DIE &Die = NewCU.getUnitDie(); + InfoHolder.addUnit(std::move(OwnedUnit)); // LTO with assembly output shares a single line table amongst multiple CUs. // To avoid the compilation directory being ambiguous, let the line table @@ -701,116 +638,89 @@ DwarfCompileUnit *DwarfDebug::constructDwarfCompileUnit(DICompileUnit DIUnit) { // compilation directory. if (!Asm->OutStreamer.hasRawTextSupport() || SingleCU) Asm->OutStreamer.getContext().setMCLineTableCompilationDir( - NewCU->getUniqueID(), CompilationDir); + 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); + 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); if (!useSplitDwarf()) { - NewCU->initStmtList(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); + NewCU.addString(Die, dwarf::DW_AT_comp_dir, CompilationDir); addGnuPubAttributes(NewCU, Die); } if (DIUnit.isOptimized()) - NewCU->addFlag(Die, dwarf::DW_AT_APPLE_optimized); + NewCU.addFlag(Die, dwarf::DW_AT_APPLE_optimized); StringRef Flags = DIUnit.getFlags(); if (!Flags.empty()) - NewCU->addString(Die, dwarf::DW_AT_APPLE_flags, Flags); + NewCU.addString(Die, dwarf::DW_AT_APPLE_flags, Flags); if (unsigned RVer = DIUnit.getRunTimeVersion()) - NewCU->addUInt(Die, dwarf::DW_AT_APPLE_major_runtime_vers, - dwarf::DW_FORM_data1, RVer); + NewCU.addUInt(Die, dwarf::DW_AT_APPLE_major_runtime_vers, + dwarf::DW_FORM_data1, RVer); if (!FirstCU) - FirstCU = NewCU; + FirstCU = &NewCU; if (useSplitDwarf()) { - NewCU->initSection(Asm->getObjFileLowering().getDwarfInfoDWOSection(), - DwarfInfoDWOSectionSym); - NewCU->setSkeleton(constructSkeletonCU(NewCU)); + NewCU.initSection(Asm->getObjFileLowering().getDwarfInfoDWOSection(), + DwarfInfoDWOSectionSym); + NewCU.setSkeleton(constructSkeletonCU(NewCU)); } else - NewCU->initSection(Asm->getObjFileLowering().getDwarfInfoSection(), - DwarfInfoSectionSym); + NewCU.initSection(Asm->getObjFileLowering().getDwarfInfoSection(), + DwarfInfoSectionSym); - CUMap.insert(std::make_pair(DIUnit, NewCU)); - CUDieMap.insert(std::make_pair(Die, NewCU)); + CUMap.insert(std::make_pair(DIUnit, &NewCU)); + CUDieMap.insert(std::make_pair(&Die, &NewCU)); return NewCU; } -// Construct subprogram DIE. -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. - - DwarfCompileUnit *&CURef = SPMap[N]; - if (CURef) - return; - CURef = TheCU; - - DISubprogram SP(N); - if (!SP.isDefinition()) - // This is a method declaration which will be handled while constructing - // class type. - return; - - DIE *SubprogramDie = TheCU->getOrCreateSubprogramDIE(SP); - - // Expose as a global name. - TheCU->addGlobalName(SP.getName(), SubprogramDie, resolve(SP.getContext())); -} - -void DwarfDebug::constructImportedEntityDIE(DwarfCompileUnit *TheCU, +void DwarfDebug::constructImportedEntityDIE(DwarfCompileUnit &TheCU, const MDNode *N) { DIImportedEntity Module(N); assert(Module.Verify()); - if (DIE *D = TheCU->getOrCreateContextDIE(Module.getContext())) - constructImportedEntityDIE(TheCU, Module, D); + if (DIE *D = TheCU.getOrCreateContextDIE(Module.getContext())) + constructImportedEntityDIE(TheCU, Module, *D); } -void DwarfDebug::constructImportedEntityDIE(DwarfCompileUnit *TheCU, - const MDNode *N, DIE *Context) { +void DwarfDebug::constructImportedEntityDIE(DwarfCompileUnit &TheCU, + const MDNode *N, DIE &Context) { DIImportedEntity Module(N); assert(Module.Verify()); return constructImportedEntityDIE(TheCU, Module, Context); } -void DwarfDebug::constructImportedEntityDIE(DwarfCompileUnit *TheCU, +void DwarfDebug::constructImportedEntityDIE(DwarfCompileUnit &TheCU, const DIImportedEntity &Module, - DIE *Context) { + DIE &Context) { assert(Module.Verify() && "Use one of the MDNode * overloads to handle invalid metadata"); - assert(Context && "Should always have a context for an imported_module"); - DIE *IMDie = new DIE(Module.getTag()); - TheCU->insertDIE(Module, IMDie); + DIE &IMDie = TheCU.createAndAddDIE(Module.getTag(), Context, Module); DIE *EntityDie; DIDescriptor Entity = resolve(Module.getEntity()); if (Entity.isNameSpace()) - EntityDie = TheCU->getOrCreateNameSpace(DINameSpace(Entity)); + EntityDie = TheCU.getOrCreateNameSpace(DINameSpace(Entity)); else if (Entity.isSubprogram()) - EntityDie = TheCU->getOrCreateSubprogramDIE(DISubprogram(Entity)); + EntityDie = TheCU.getOrCreateSubprogramDIE(DISubprogram(Entity)); else if (Entity.isType()) - EntityDie = TheCU->getOrCreateTypeDIE(DIType(Entity)); + EntityDie = TheCU.getOrCreateTypeDIE(DIType(Entity)); else - EntityDie = TheCU->getDIE(Entity); - TheCU->addSourceLine(IMDie, Module.getLineNumber(), - Module.getContext().getFilename(), - Module.getContext().getDirectory()); - TheCU->addDIEEntry(IMDie, dwarf::DW_AT_import, EntityDie); + EntityDie = TheCU.getDIE(Entity); + 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()) - TheCU->addString(IMDie, dwarf::DW_AT_name, Name); - Context->addChild(IMDie); + TheCU.addString(IMDie, dwarf::DW_AT_name, Name); } // Emit all Dwarf sections that should come prior to the content. Create @@ -836,7 +746,7 @@ void DwarfDebug::beginModule() { for (MDNode *N : CU_Nodes->operands()) { DICompileUnit CUNode(N); - DwarfCompileUnit *CU = constructDwarfCompileUnit(CUNode); + DwarfCompileUnit &CU = constructDwarfCompileUnit(CUNode); DIArray ImportedEntities = CUNode.getImportedEntities(); for (unsigned i = 0, e = ImportedEntities.getNumElements(); i != e; ++i) ScopesWithImportedEntities.push_back(std::make_pair( @@ -846,20 +756,20 @@ void DwarfDebug::beginModule() { ScopesWithImportedEntities.end(), less_first()); DIArray GVs = CUNode.getGlobalVariables(); for (unsigned i = 0, e = GVs.getNumElements(); i != e; ++i) - CU->createGlobalVariableDIE(DIGlobalVariable(GVs.getElement(i))); + CU.createGlobalVariableDIE(DIGlobalVariable(GVs.getElement(i))); DIArray SPs = CUNode.getSubprograms(); for (unsigned i = 0, e = SPs.getNumElements(); i != e; ++i) - constructSubprogramDIE(CU, SPs.getElement(i)); + SPMap.insert(std::make_pair(SPs.getElement(i), &CU)); DIArray EnumTypes = CUNode.getEnumTypes(); for (unsigned i = 0, e = EnumTypes.getNumElements(); i != e; ++i) - CU->getOrCreateTypeDIE(EnumTypes.getElement(i)); + CU.getOrCreateTypeDIE(EnumTypes.getElement(i)); DIArray RetainedTypes = CUNode.getRetainedTypes(); 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); + CU.getOrCreateTypeDIE(UniqueTy); } // Emit imported_modules last so that the relevant context is already // available. @@ -874,20 +784,41 @@ void DwarfDebug::beginModule() { SectionMap[Asm->getObjFileLowering().getTextSection()]; } -// Attach DW_AT_inline attribute with inlined subprogram DIEs. -void DwarfDebug::computeInlinedDIEs() { - // Attach DW_AT_inline attribute with inlined subprogram DIEs. - for (DIE *ISP : InlinedSubprogramDIEs) - FirstCU->addUInt(ISP, dwarf::DW_AT_inline, None, dwarf::DW_INL_inlined); +void DwarfDebug::finishSubprogramDefinitions() { + const Module *M = MMI->getModule(); - 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); + NamedMDNode *CU_Nodes = M->getNamedMetadata("llvm.dbg.cu"); + for (MDNode *N : CU_Nodes->operands()) { + DICompileUnit TheCU(N); + // Construct subprogram DIE and add variables DIEs. + DwarfCompileUnit *SPCU = + static_cast<DwarfCompileUnit *>(CUMap.lookup(TheCU)); + DIArray Subprograms = TheCU.getSubprograms(); + for (unsigned i = 0, e = Subprograms.getNumElements(); i != e; ++i) { + DISubprogram SP(Subprograms.getElement(i)); + // Perhaps the subprogram is in another CU (such as due to comdat + // folding, etc), in which case ignore it here. + if (SPMap[SP] != SPCU) + continue; + DIE *D = SPCU->getDIE(SP); + if (DIE *AbsSPDIE = AbstractSPDies.lookup(SP)) { + if (D) + // If this subprogram has an abstract definition, reference that + SPCU->addDIEEntry(*D, dwarf::DW_AT_abstract_origin, *AbsSPDIE); + } else { + if (!D) + // Lazily construct the subprogram if we didn't see either concrete or + // inlined versions during codegen. + D = SPCU->getOrCreateSubprogramDIE(SP); + // And attach the attributes + SPCU->applySubprogramAttributes(SP, *D); + SPCU->addGlobalName(SP.getName(), *D, resolve(SP.getContext())); + } + } } } + // Collect info for variables that were optimized out. void DwarfDebug::collectDeadVariables() { const Module *M = MMI->getModule(); @@ -895,34 +826,32 @@ void DwarfDebug::collectDeadVariables() { if (NamedMDNode *CU_Nodes = M->getNamedMetadata("llvm.dbg.cu")) { for (MDNode *N : CU_Nodes->operands()) { DICompileUnit TheCU(N); + // Construct subprogram DIE and add variables DIEs. + DwarfCompileUnit *SPCU = + static_cast<DwarfCompileUnit *>(CUMap.lookup(TheCU)); + assert(SPCU && "Unable to find Compile Unit!"); DIArray Subprograms = TheCU.getSubprograms(); for (unsigned i = 0, e = Subprograms.getNumElements(); i != e; ++i) { DISubprogram SP(Subprograms.getElement(i)); if (ProcessedSPNodes.count(SP) != 0) continue; - if (!SP.isSubprogram()) - continue; - if (!SP.isDefinition()) - continue; + assert(SP.isSubprogram() && + "CU's subprogram list contains a non-subprogram"); + assert(SP.isDefinition() && + "CU's subprogram list contains a subprogram declaration"); DIArray Variables = SP.getVariables(); if (Variables.getNumElements() == 0) continue; - // Construct subprogram DIE and add variables DIEs. - 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. - constructSubprogramDIE(SPCU, SP); - DIE *SPDIE = SPCU->getDIE(SP); + DIE *SPDIE = AbstractSPDies.lookup(SP); + if (!SPDIE) + SPDIE = SPCU->getDIE(SP); + assert(SPDIE); for (unsigned vi = 0, ve = Variables.getNumElements(); vi != ve; ++vi) { DIVariable DV(Variables.getElement(vi)); - if (!DV.isVariable()) - continue; - DbgVariable NewVar(DV, NULL, this); - if (DIE *VariableDIE = SPCU->constructVariableDIE(NewVar, false)) - SPDIE->addChild(VariableDIE); + assert(DV.isVariable()); + DbgVariable NewVar(DV, nullptr, this); + SPDIE->addChild(SPCU->constructVariableDIE(NewVar)); } } } @@ -930,28 +859,27 @@ void DwarfDebug::collectDeadVariables() { } void DwarfDebug::finalizeModuleInfo() { + finishSubprogramDefinitions(); + // Collect info for variables that were optimized out. collectDeadVariables(); - // Attach DW_AT_inline attribute with inlined subprogram DIEs. - computeInlinedDIEs(); - // Handle anything that needs to be done on a per-unit basis after // all other generation. - for (DwarfUnit *TheU : getUnits()) { + for (const auto &TheU : getUnits()) { // Emit DW_AT_containing_type attribute to connect types with their // vtable holding type. TheU->constructContainingTypeDIEs(); // Add CU specific attributes if we need to add any. - if (TheU->getUnitDie()->getTag() == dwarf::DW_TAG_compile_unit) { + 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()); + 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, @@ -959,12 +887,12 @@ void DwarfDebug::finalizeModuleInfo() { // 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(), + if (!AddrPool.isEmpty()) + addSectionLabel(*Asm, *SkCU, SkCU->getUnitDie(), dwarf::DW_AT_GNU_addr_base, DwarfAddrSectionSym, DwarfAddrSectionSym); if (!TheU->getRangeLists().empty()) - addSectionLabel(Asm, SkCU, SkCU->getUnitDie(), + addSectionLabel(*Asm, *SkCU, SkCU->getUnitDie(), dwarf::DW_AT_GNU_ranges_base, DwarfDebugRangeSectionSym, DwarfDebugRangeSectionSym); } @@ -975,26 +903,27 @@ void DwarfDebug::finalizeModuleInfo() { // 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); + 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()), + 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); + 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()); + U.addLocalLabelAddress(U.getUnitDie(), dwarf::DW_AT_low_pc, + Range.getStart()); + U.addLabelDelta(U.getUnitDie(), dwarf::DW_AT_high_pc, Range.getEnd(), + Range.getStart()); } } } @@ -1018,7 +947,7 @@ void DwarfDebug::endSections() { // Some symbols (e.g. common/bss on mach-o) can have no section but still // appear in the output. This sucks as we rely on sections to build // arange spans. We can do it without, but it's icky. - SectionMap[NULL].push_back(SCU); + SectionMap[nullptr].push_back(SCU); } } @@ -1036,7 +965,7 @@ void DwarfDebug::endSections() { // Add terminating symbols for each section. for (unsigned ID = 0, E = Sections.size(); ID != E; ID++) { const MCSection *Section = Sections[ID]; - MCSymbol *Sym = NULL; + MCSymbol *Sym = nullptr; if (Section) { // We can't call MCSection::getLabelEndName, as it's only safe to do so @@ -1049,14 +978,14 @@ void DwarfDebug::endSections() { } // Insert a final terminator. - SectionMap[Section].push_back(SymbolCU(NULL, Sym)); + SectionMap[Section].push_back(SymbolCU(nullptr, Sym)); } } // Emit all Dwarf sections that should come after the content. void DwarfDebug::endModule() { - assert(CurFn == 0); - assert(CurMI == 0); + assert(CurFn == nullptr); + assert(CurMI == nullptr); if (!FirstCU) return; @@ -1089,7 +1018,7 @@ void DwarfDebug::endModule() { emitDebugAbbrevDWO(); emitDebugLineDWO(); // Emit DWO addresses. - InfoHolder.emitAddresses(Asm->getObjFileLowering().getDwarfAddrSection()); + AddrPool.emit(*Asm, Asm->getObjFileLowering().getDwarfAddrSection()); emitDebugLocDWO(); } else // Emit info into a debug loc section. @@ -1111,29 +1040,34 @@ void DwarfDebug::endModule() { // clean up. SPMap.clear(); + AbstractVariables.clear(); // Reset these for the next Module if we have one. - FirstCU = NULL; + FirstCU = nullptr; } // Find abstract variable, if any, associated with Var. DbgVariable *DwarfDebug::findAbstractVariable(DIVariable &DV, DebugLoc ScopeLoc) { + return findAbstractVariable(DV, ScopeLoc.getScope(DV->getContext())); +} + +DbgVariable *DwarfDebug::findAbstractVariable(DIVariable &DV, + const MDNode *ScopeNode) { LLVMContext &Ctx = DV->getContext(); // More then one inlined variable corresponds to one abstract variable. DIVariable Var = cleanseInlinedVariable(DV, Ctx); - DbgVariable *AbsDbgVariable = AbstractVariables.lookup(Var); - if (AbsDbgVariable) - return AbsDbgVariable; + auto I = AbstractVariables.find(Var); + if (I != AbstractVariables.end()) + return I->second.get(); - LexicalScope *Scope = LScopes.findAbstractScope(ScopeLoc.getScope(Ctx)); + LexicalScope *Scope = LScopes.findAbstractScope(ScopeNode); if (!Scope) - return NULL; + return nullptr; - AbsDbgVariable = new DbgVariable(Var, NULL, this); - addScopeVariable(Scope, AbsDbgVariable); - AbstractVariables[Var] = AbsDbgVariable; - return AbsDbgVariable; + auto AbsDbgVariable = make_unique<DbgVariable>(Var, nullptr, this); + addScopeVariable(Scope, AbsDbgVariable.get()); + return (AbstractVariables[Var] = std::move(AbsDbgVariable)).get(); } // If Var is a current function argument then add it to CurrentFnArguments list. @@ -1169,7 +1103,7 @@ void DwarfDebug::collectVariableInfoFromMMITable( LexicalScope *Scope = LScopes.findLexicalScope(VI.Loc); // If variable scope is not found then skip this variable. - if (Scope == 0) + if (!Scope) continue; DbgVariable *AbsDbgVariable = findAbstractVariable(DV, VI.Loc); @@ -1177,28 +1111,12 @@ void DwarfDebug::collectVariableInfoFromMMITable( RegVar->setFrameIndex(VI.Slot); if (!addCurrentFnArgument(RegVar, Scope)) addScopeVariable(Scope, RegVar); - if (AbsDbgVariable) - AbsDbgVariable->setFrameIndex(VI.Slot); } } -// Return true if debug value, encoded by DBG_VALUE instruction, is in a -// 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() && - (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 DebugLocEntry getDebugLocEntry(AsmPrinter *Asm, - const MCSymbol *FLabel, - const MCSymbol *SLabel, - const MachineInstr *MI, - DwarfCompileUnit *Unit) { - const MDNode *Var = MI->getOperand(MI->getNumOperands() - 1).getMetadata(); +static DebugLocEntry::Value getDebugLocValue(const MachineInstr *MI) { + const MDNode *Var = MI->getDebugVariable(); assert(MI->getNumOperands() == 3); if (MI->getOperand(0).isReg()) { @@ -1209,14 +1127,14 @@ static DebugLocEntry getDebugLocEntry(AsmPrinter *Asm, MLoc.set(MI->getOperand(0).getReg()); else MLoc.set(MI->getOperand(0).getReg(), MI->getOperand(1).getImm()); - return DebugLocEntry(FLabel, SLabel, MLoc, Var, Unit); + return DebugLocEntry::Value(Var, MLoc); } if (MI->getOperand(0).isImm()) - return DebugLocEntry(FLabel, SLabel, MI->getOperand(0).getImm(), Unit); + return DebugLocEntry::Value(Var, MI->getOperand(0).getImm()); if (MI->getOperand(0).isFPImm()) - return DebugLocEntry(FLabel, SLabel, MI->getOperand(0).getFPImm(), Unit); + return DebugLocEntry::Value(Var, MI->getOperand(0).getFPImm()); if (MI->getOperand(0).isCImm()) - return DebugLocEntry(FLabel, SLabel, MI->getOperand(0).getCImm(), Unit); + return DebugLocEntry::Value(Var, MI->getOperand(0).getCImm()); llvm_unreachable("Unexpected 3 operand DBG_VALUE instruction!"); } @@ -1224,35 +1142,38 @@ static DebugLocEntry getDebugLocEntry(AsmPrinter *Asm, // Find variables for each lexical scope. void DwarfDebug::collectVariableInfo(SmallPtrSet<const MDNode *, 16> &Processed) { + LexicalScope *FnScope = LScopes.getCurrentFunctionScope(); + DwarfCompileUnit *TheCU = SPMap.lookup(FnScope->getScopeNode()); // Grab the variable info that was squirreled away in the MMI side-table. collectVariableInfoFromMMITable(Processed); - for (const MDNode *Var : UserVariables) { - if (Processed.count(Var)) + for (const auto &I : DbgValues) { + DIVariable DV(I.first); + if (Processed.count(DV)) continue; - // History contains relevant DBG_VALUE instructions for Var and instructions - // clobbering it. - SmallVectorImpl<const MachineInstr *> &History = DbgValues[Var]; - if (History.empty()) + // Instruction ranges, specifying where DV is accessible. + const auto &Ranges = I.second; + if (Ranges.empty()) continue; - const MachineInstr *MInsn = History.front(); - DIVariable DV(Var); - LexicalScope *Scope = NULL; + LexicalScope *Scope = nullptr; if (DV.getTag() == dwarf::DW_TAG_arg_variable && DISubprogram(DV.getContext()).describes(CurFn->getFunction())) Scope = LScopes.getCurrentFunctionScope(); - else if (MDNode *IA = DV.getInlinedAt()) - Scope = LScopes.findInlinedScope(DebugLoc::getFromDILocation(IA)); - else - Scope = LScopes.findLexicalScope(cast<MDNode>(DV->getOperand(1))); + else if (MDNode *IA = DV.getInlinedAt()) { + DebugLoc DL = DebugLoc::getFromDILocation(IA); + Scope = LScopes.findInlinedScope(DebugLoc::get( + DL.getLine(), DL.getCol(), DV.getContext(), IA)); + } else + Scope = LScopes.findLexicalScope(DV.getContext()); // If variable scope is not found then skip this variable. if (!Scope) continue; Processed.insert(DV); + const MachineInstr *MInsn = Ranges.front().first; assert(MInsn->isDebugValue() && "History must begin with debug value"); DbgVariable *AbsVar = findAbstractVariable(DV, MInsn->getDebugLoc()); DbgVariable *RegVar = new DbgVariable(DV, AbsVar, this); @@ -1261,9 +1182,8 @@ DwarfDebug::collectVariableInfo(SmallPtrSet<const MDNode *, 16> &Processed) { if (AbsVar) AbsVar->setMInsn(MInsn); - // Simplify ranges that are fully coalesced. - if (History.size() <= 1 || - (History.size() == 2 && MInsn->isIdenticalTo(History.back()))) { + // Check if the first DBG_VALUE is valid for the rest of the function. + if (Ranges.size() == 1 && Ranges.front().second == nullptr) { RegVar->setMInsn(MInsn); continue; } @@ -1276,58 +1196,48 @@ DwarfDebug::collectVariableInfo(SmallPtrSet<const MDNode *, 16> &Processed) { 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; + for (auto I = Ranges.begin(), E = Ranges.end(); I != E; ++I) { + const MachineInstr *Begin = I->first; + const MachineInstr *End = I->second; assert(Begin->isDebugValue() && "Invalid History entry"); - // Check if DBG_VALUE is truncating a range. + // Check if a variable is unaccessible in this range. if (Begin->getNumOperands() > 1 && Begin->getOperand(0).isReg() && !Begin->getOperand(0).getReg()) continue; - // Compute the range for a register location. - const MCSymbol *FLabel = getLabelBeforeInsn(Begin); - const MCSymbol *SLabel = 0; - - if (HI + 1 == HE) - // If Begin is the last instruction in History then its value is valid - // until the end of the function. - SLabel = FunctionEndSym; - else { - const MachineInstr *End = HI[1]; - DEBUG(dbgs() << "DotDebugLoc Pair:\n" - << "\t" << *Begin << "\t" << *End << "\n"); - if (End->isDebugValue()) - SLabel = getLabelBeforeInsn(End); - else { - // End is a normal instruction clobbering the range. - SLabel = getLabelAfterInsn(End); - assert(SLabel && "Forgot label after clobber instruction"); - ++HI; - } - } + const MCSymbol *StartLabel = getLabelBeforeInsn(Begin); + assert(StartLabel && "Forgot label before DBG_VALUE starting a range!"); + + const MCSymbol *EndLabel; + if (End != nullptr) + EndLabel = getLabelAfterInsn(End); + else if (std::next(I) == Ranges.end()) + EndLabel = FunctionEndSym; + else + EndLabel = getLabelBeforeInsn(std::next(I)->first); + assert(EndLabel && "Forgot label after instruction ending a range!"); - // The value is valid until the next DBG_VALUE or clobber. - LexicalScope *FnScope = LScopes.getCurrentFunctionScope(); - DwarfCompileUnit *TheCU = SPMap.lookup(FnScope->getScopeNode()); - DebugLocEntry Loc = getDebugLocEntry(Asm, FLabel, SLabel, Begin, TheCU); + DEBUG(dbgs() << "DotDebugLoc Pair:\n" + << "\t" << *Begin << "\t" << *End << "\n"); + DebugLocEntry Loc(StartLabel, EndLabel, getDebugLocValue(Begin), TheCU); if (DebugLoc.empty() || !DebugLoc.back().Merge(Loc)) DebugLoc.push_back(std::move(Loc)); } } // Collect info for variables that were optimized out. - LexicalScope *FnScope = LScopes.getCurrentFunctionScope(); DIArray Variables = DISubprogram(FnScope->getScopeNode()).getVariables(); for (unsigned i = 0, e = Variables.getNumElements(); i != e; ++i) { DIVariable DV(Variables.getElement(i)); - if (!DV || !DV.isVariable() || !Processed.insert(DV)) + assert(DV.isVariable()); + if (!Processed.insert(DV)) continue; if (LexicalScope *Scope = LScopes.findLexicalScope(DV.getContext())) - addScopeVariable(Scope, new DbgVariable(DV, NULL, this)); + addScopeVariable( + Scope, + new DbgVariable(DV, findAbstractVariable(DV, Scope->getScopeNode()), + this)); } } @@ -1345,7 +1255,7 @@ MCSymbol *DwarfDebug::getLabelAfterInsn(const MachineInstr *MI) { // Process beginning of an instruction. void DwarfDebug::beginInstruction(const MachineInstr *MI) { - assert(CurMI == 0); + assert(CurMI == nullptr); CurMI = MI; // Check if source location changes, but ignore DBG_VALUE locations. if (!MI->isDebugValue()) { @@ -1364,7 +1274,7 @@ void DwarfDebug::beginInstruction(const MachineInstr *MI) { const MDNode *Scope = DL.getScope(Asm->MF->getFunction()->getContext()); recordSourceLine(DL.getLine(), DL.getCol(), Scope, Flags); } else - recordSourceLine(0, 0, 0, 0); + recordSourceLine(0, 0, nullptr, 0); } } @@ -1389,15 +1299,15 @@ void DwarfDebug::beginInstruction(const MachineInstr *MI) { // Process end of an instruction. void DwarfDebug::endInstruction() { - assert(CurMI != 0); + assert(CurMI != nullptr); // Don't create a new label after DBG_VALUE instructions. // They don't generate code. if (!CurMI->isDebugValue()) - PrevLabel = 0; + PrevLabel = nullptr; DenseMap<const MachineInstr *, MCSymbol *>::iterator I = LabelsAfterInsn.find(CurMI); - CurMI = 0; + CurMI = nullptr; // No label needed. if (I == LabelsAfterInsn.end()) @@ -1441,6 +1351,17 @@ void DwarfDebug::identifyScopeMarkers() { } } +static DebugLoc findPrologueEndLoc(const MachineFunction *MF) { + // First known non-DBG_VALUE and non-frame setup location marks + // the beginning of the function body. + for (const auto &MBB : *MF) + for (const auto &MI : MBB) + if (!MI.isDebugValue() && !MI.getFlag(MachineInstr::FrameSetup) && + !MI.getDebugLoc().isUnknown()) + return MI.getDebugLoc(); + 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) { @@ -1456,7 +1377,7 @@ void DwarfDebug::beginFunction(const MachineFunction *MF) { if (LScopes.empty()) return; - assert(UserVariables.empty() && DbgValues.empty() && "Maps weren't cleaned"); + assert(DbgValues.empty() && "DbgValues map wasn't cleaned!"); // Make sure that each lexical scope will have a begin/end label. identifyScopeMarkers(); @@ -1478,144 +1399,26 @@ void DwarfDebug::beginFunction(const MachineFunction *MF) { // Assumes in correct section after the entry point. Asm->OutStreamer.EmitLabel(FunctionBeginSym); - const TargetRegisterInfo *TRI = Asm->TM.getRegisterInfo(); - // LiveUserVar - Map physreg numbers to the MDNode they contain. - std::vector<const MDNode *> LiveUserVar(TRI->getNumRegs()); - - for (MachineFunction::const_iterator I = MF->begin(), E = MF->end(); I != E; - ++I) { - bool AtBlockEntry = true; - for (MachineBasicBlock::const_iterator II = I->begin(), IE = I->end(); - II != IE; ++II) { - const MachineInstr *MI = II; - - if (MI->isDebugValue()) { - assert(MI->getNumOperands() > 1 && "Invalid machine instruction!"); - - // Keep track of user variables. - const MDNode *Var = - MI->getOperand(MI->getNumOperands() - 1).getMetadata(); - - // Variable is in a register, we need to check for clobbers. - if (isDbgValueInDefinedReg(MI)) - LiveUserVar[MI->getOperand(0).getReg()] = Var; - - // Check the history of this variable. - SmallVectorImpl<const MachineInstr *> &History = DbgValues[Var]; - if (History.empty()) { - UserVariables.push_back(Var); - // The first mention of a function argument gets the FunctionBeginSym - // label, so arguments are visible when breaking at function entry. - DIVariable DV(Var); - if (DV.isVariable() && DV.getTag() == dwarf::DW_TAG_arg_variable && - getDISubprogram(DV.getContext()).describes(MF->getFunction())) - LabelsBeforeInsn[MI] = FunctionBeginSym; - } else { - // We have seen this variable before. Try to coalesce DBG_VALUEs. - const MachineInstr *Prev = History.back(); - if (Prev->isDebugValue()) { - // Coalesce identical entries at the end of History. - if (History.size() >= 2 && - Prev->isIdenticalTo(History[History.size() - 2])) { - DEBUG(dbgs() << "Coalescing identical DBG_VALUE entries:\n" - << "\t" << *Prev << "\t" - << *History[History.size() - 2] << "\n"); - History.pop_back(); - } - - // Terminate old register assignments that don't reach MI; - MachineFunction::const_iterator PrevMBB = Prev->getParent(); - if (PrevMBB != I && (!AtBlockEntry || std::next(PrevMBB) != I) && - isDbgValueInDefinedReg(Prev)) { - // Previous register assignment needs to terminate at the end of - // its basic block. - MachineBasicBlock::const_iterator LastMI = - PrevMBB->getLastNonDebugInstr(); - if (LastMI == PrevMBB->end()) { - // Drop DBG_VALUE for empty range. - DEBUG(dbgs() << "Dropping DBG_VALUE for empty range:\n" - << "\t" << *Prev << "\n"); - History.pop_back(); - } else if (std::next(PrevMBB) != PrevMBB->getParent()->end()) - // Terminate after LastMI. - History.push_back(LastMI); - } - } - } - History.push_back(MI); - } else { - // Not a DBG_VALUE instruction. - if (!MI->isPosition()) - AtBlockEntry = false; - - // First known non-DBG_VALUE and non-frame setup location marks - // the beginning of the function body. - if (!MI->getFlag(MachineInstr::FrameSetup) && - (PrologEndLoc.isUnknown() && !MI->getDebugLoc().isUnknown())) - PrologEndLoc = MI->getDebugLoc(); - - // Check if the instruction clobbers any registers with debug vars. - for (const MachineOperand &MO : MI->operands()) { - if (!MO.isReg() || !MO.isDef() || !MO.getReg()) - continue; - for (MCRegAliasIterator AI(MO.getReg(), TRI, true); AI.isValid(); - ++AI) { - unsigned Reg = *AI; - const MDNode *Var = LiveUserVar[Reg]; - if (!Var) - continue; - // Reg is now clobbered. - LiveUserVar[Reg] = 0; - - // Was MD last defined by a DBG_VALUE referring to Reg? - DbgValueHistoryMap::iterator HistI = DbgValues.find(Var); - if (HistI == DbgValues.end()) - continue; - SmallVectorImpl<const MachineInstr *> &History = HistI->second; - if (History.empty()) - continue; - const MachineInstr *Prev = History.back(); - // Sanity-check: Register assignments are terminated at the end of - // their block. - if (!Prev->isDebugValue() || Prev->getParent() != MI->getParent()) - continue; - // Is the variable still in Reg? - if (!isDbgValueInDefinedReg(Prev) || - Prev->getOperand(0).getReg() != Reg) - continue; - // Var is clobbered. Make sure the next instruction gets a label. - History.push_back(MI); - } - } - } - } - } + // Calculate history for local variables. + calculateDbgValueHistory(MF, Asm->TM.getRegisterInfo(), DbgValues); - for (auto &I : DbgValues) { - SmallVectorImpl<const MachineInstr *> &History = I.second; - if (History.empty()) + // Request labels for the full history. + for (const auto &I : DbgValues) { + const auto &Ranges = I.second; + if (Ranges.empty()) continue; - // Make sure the final register assignments are terminated. - const MachineInstr *Prev = History.back(); - if (Prev->isDebugValue() && isDbgValueInDefinedReg(Prev)) { - const MachineBasicBlock *PrevMBB = Prev->getParent(); - MachineBasicBlock::const_iterator LastMI = - PrevMBB->getLastNonDebugInstr(); - if (LastMI == PrevMBB->end()) - // Drop DBG_VALUE for empty range. - History.pop_back(); - else if (PrevMBB != &PrevMBB->getParent()->back()) { - // Terminate after LastMI. - History.push_back(LastMI); - } - } - // Request labels for the full history. - for (const MachineInstr *MI : History) { - if (MI->isDebugValue()) - requestLabelBeforeInsn(MI); - else - requestLabelAfterInsn(MI); + // The first mention of a function argument gets the FunctionBeginSym + // label, so arguments are visible when breaking at function entry. + DIVariable DV(I.first); + if (DV.isVariable() && DV.getTag() == dwarf::DW_TAG_arg_variable && + getDISubprogram(DV.getContext()).describes(MF->getFunction())) + LabelsBeforeInsn[Ranges.front().first] = FunctionBeginSym; + + for (const auto &Range : Ranges) { + requestLabelBeforeInsn(Range.first); + if (Range.second) + requestLabelAfterInsn(Range.second); } } @@ -1623,6 +1426,7 @@ void DwarfDebug::beginFunction(const MachineFunction *MF) { PrevLabel = FunctionBeginSym; // Record beginning of function. + PrologEndLoc = findPrologueEndLoc(MF); if (!PrologEndLoc.isUnknown()) { DebugLoc FnStartDL = PrologEndLoc.getFnDebugLoc(MF->getFunction()->getContext()); @@ -1671,11 +1475,11 @@ void DwarfDebug::endFunction(const MachineFunction *MF) { // 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) + if (!CurFn) CurFn = MF; else assert(CurFn == MF); - assert(CurFn != 0); + assert(CurFn != nullptr); if (!MMI->hasDebugInfo() || LScopes.empty()) { // If we don't have a lexical scope for this function then there will @@ -1683,7 +1487,7 @@ void DwarfDebug::endFunction(const MachineFunction *MF) { // previously used section to nullptr. PrevSection = nullptr; PrevCU = nullptr; - CurFn = 0; + CurFn = nullptr; return; } @@ -1699,55 +1503,50 @@ void DwarfDebug::endFunction(const MachineFunction *MF) { collectVariableInfo(ProcessedVars); LexicalScope *FnScope = LScopes.getCurrentFunctionScope(); - DwarfCompileUnit *TheCU = SPMap.lookup(FnScope->getScopeNode()); - assert(TheCU && "Unable to find compile unit!"); + DwarfCompileUnit &TheCU = *SPMap.lookup(FnScope->getScopeNode()); // Construct abstract scopes. for (LexicalScope *AScope : LScopes.getAbstractScopesList()) { DISubprogram SP(AScope->getScopeNode()); - if (SP.isSubprogram()) { - // Collect info for variables that were optimized out. - DIArray Variables = SP.getVariables(); - for (unsigned i = 0, e = Variables.getNumElements(); i != e; ++i) { - DIVariable DV(Variables.getElement(i)); - if (!DV || !DV.isVariable() || !ProcessedVars.insert(DV)) - continue; - // Check that DbgVariable for DV wasn't created earlier, when - // findAbstractVariable() was called for inlined instance of DV. - LLVMContext &Ctx = DV->getContext(); - DIVariable CleanDV = cleanseInlinedVariable(DV, Ctx); - if (AbstractVariables.lookup(CleanDV)) - continue; - if (LexicalScope *Scope = LScopes.findAbstractScope(DV.getContext())) - addScopeVariable(Scope, new DbgVariable(DV, NULL, this)); - } + if (!SP.isSubprogram()) + continue; + // Collect info for variables that were optimized out. + DIArray Variables = SP.getVariables(); + for (unsigned i = 0, e = Variables.getNumElements(); i != e; ++i) { + DIVariable DV(Variables.getElement(i)); + assert(DV && DV.isVariable()); + if (!ProcessedVars.insert(DV)) + continue; + findAbstractVariable(DV, DV.getContext()); } - if (ProcessedSPNodes.count(AScope->getScopeNode()) == 0) - constructScopeDIE(TheCU, AScope); + constructAbstractSubprogramScopeDIE(TheCU, AScope); } - DIE *CurFnDIE = constructScopeDIE(TheCU, FnScope); + DIE &CurFnDIE = constructSubprogramScopeDIE(TheCU, FnScope); if (!CurFn->getTarget().Options.DisableFramePointerElim(*CurFn)) - TheCU->addFlag(CurFnDIE, dwarf::DW_AT_APPLE_omit_frame_ptr); + 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)); + TheCU.addRange(std::move(Span)); PrevSection = Asm->getCurrentSection(); - PrevCU = TheCU; + PrevCU = &TheCU; // Clear debug info - for (auto &I : ScopeVariables) - DeleteContainerPointers(I.second); + // Ownership of DbgVariables is a bit subtle - ScopeVariables owns all the + // DbgVariables except those that are also in AbstractVariables (since they + // can be used cross-function) + for (const auto &I : ScopeVariables) + for (const auto *Var : I.second) + if (!AbstractVariables.count(Var->getVariable()) || Var->getAbstractVariable()) + delete Var; ScopeVariables.clear(); DeleteContainerPointers(CurrentFnArguments); - UserVariables.clear(); DbgValues.clear(); - AbstractVariables.clear(); LabelsBeforeInsn.clear(); LabelsAfterInsn.clear(); - PrevLabel = NULL; - CurFn = 0; + PrevLabel = nullptr; + CurFn = nullptr; } // Register a source line with debug info. Returns the unique label that was @@ -1758,36 +1557,16 @@ void DwarfDebug::recordSourceLine(unsigned Line, unsigned Col, const MDNode *S, StringRef Dir; unsigned Src = 1; unsigned Discriminator = 0; - if (S) { - DIDescriptor Scope(S); - - if (Scope.isCompileUnit()) { - DICompileUnit CU(S); - Fn = CU.getFilename(); - Dir = CU.getDirectory(); - } else if (Scope.isFile()) { - DIFile F(S); - Fn = F.getFilename(); - Dir = F.getDirectory(); - } else if (Scope.isSubprogram()) { - DISubprogram SP(S); - Fn = SP.getFilename(); - Dir = SP.getDirectory(); - } else if (Scope.isLexicalBlockFile()) { - DILexicalBlockFile DBF(S); - Fn = DBF.getFilename(); - Dir = DBF.getDirectory(); - } else if (Scope.isLexicalBlock()) { - DILexicalBlock DB(S); - Fn = DB.getFilename(); - Dir = DB.getDirectory(); - Discriminator = DB.getDiscriminator(); - } else - llvm_unreachable("Unexpected scope info"); + if (DIScope Scope = DIScope(S)) { + assert(Scope.isScope()); + Fn = Scope.getFilename(); + Dir = Scope.getDirectory(); + if (Scope.isLexicalBlock()) + Discriminator = DILexicalBlock(S).getDiscriminator(); unsigned CUID = Asm->OutStreamer.getContext().getDwarfCompileUnitID(); - Src = static_cast<DwarfCompileUnit *>(InfoHolder.getUnits()[CUID]) - ->getOrCreateSourceID(Fn, Dir); + Src = static_cast<DwarfCompileUnit &>(*InfoHolder.getUnits()[CUID]) + .getOrCreateSourceID(Fn, Dir); } Asm->OutStreamer.EmitDwarfLocDirective(Src, Line, Col, Flags, 0, Discriminator, Fn); @@ -1797,68 +1576,6 @@ void DwarfDebug::recordSourceLine(unsigned Line, unsigned Col, const MDNode *S, // Emit Methods //===----------------------------------------------------------------------===// -// 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 DwarfFile::computeSizeAndOffset(DIE *Die, unsigned Offset) { - // Record the abbreviation. - assignAbbrevNumber(Die->getAbbrev()); - - // Get the abbreviation for this DIE. - const DIEAbbrev &Abbrev = Die->getAbbrev(); - - // Set DIE offset - Die->setOffset(Offset); - - // Start the size with the size of abbreviation code. - Offset += getULEB128Size(Die->getAbbrevNumber()); - - 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.hasChildren() && "Children flag not set"); - - for (DIE *Child : Children) - Offset = computeSizeAndOffset(Child, Offset); - - // End of children marker. - Offset += sizeof(int8_t); - } - - Die->setSize(Offset - Die->getOffset()); - return Offset; -} - -// Compute the size and offset for each DIE. -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 (DwarfUnit *TheU : CUs) { - TheU->setDebugInfoOffset(SecOffset); - - // CU-relative offset is reset to 0 here. - 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(TheU->getUnitDie(), Offset); - SecOffset += EndOffset; - } -} - // Emit initial Dwarf sections with a label at the start of each one. void DwarfDebug::emitSectionLabels() { const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering(); @@ -1906,19 +1623,19 @@ void DwarfDebug::emitSectionLabels() { } // Recursively emits a debug information entry. -void DwarfDebug::emitDIE(DIE *Die) { +void DwarfDebug::emitDIE(DIE &Die) { // Get the abbreviation for this DIE. - const DIEAbbrev &Abbrev = Die->getAbbrev(); + const DIEAbbrev &Abbrev = Die.getAbbrev(); // Emit the code (index) for the abbreviation. if (Asm->isVerbose()) Asm->OutStreamer.AddComment("Abbrev [" + Twine(Abbrev.getNumber()) + - "] 0x" + Twine::utohexstr(Die->getOffset()) + - ":0x" + Twine::utohexstr(Die->getSize()) + " " + + "] 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<DIEValue *> &Values = Die.getValues(); const SmallVectorImpl<DIEAbbrevData> &AbbrevData = Abbrev.getData(); // Emit the DIE attribute values. @@ -1940,38 +1657,14 @@ void DwarfDebug::emitDIE(DIE *Die) { // Emit the DIE children if any. if (Abbrev.hasChildren()) { - const std::vector<DIE *> &Children = Die->getChildren(); - - for (DIE *Child : Children) - emitDIE(Child); + for (auto &Child : Die.getChildren()) + emitDIE(*Child); 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 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(TheU->getLabelBegin()); - - // Emit size of content not including length itself - Asm->OutStreamer.AddComment("Length of Unit"); - Asm->EmitInt32(TheU->getHeaderSize() + Die->getSize()); - - TheU->emitHeader(ASectionSym); - - DD->emitDIE(Die); - Asm->OutStreamer.EmitLabel(TheU->getLabelEnd()); - } -} - // Emit the debug info section. void DwarfDebug::emitDebugInfo() { DwarfFile &Holder = useSplitDwarf() ? SkeletonHolder : InfoHolder; @@ -1986,26 +1679,6 @@ void DwarfDebug::emitAbbreviations() { Holder.emitAbbrevs(Asm->getObjFileLowering().getDwarfAbbrevSection()); } -void DwarfFile::emitAbbrevs(const MCSection *Section) { - // Check to see if it is worth the effort. - if (!Abbreviations.empty()) { - // Start the debug abbrev section. - Asm->OutStreamer.SwitchSection(Section); - - // For each abbrevation. - for (const DIEAbbrev *Abbrev : Abbreviations) { - // Emit the abbrevations code (base 1 index.) - Asm->EmitULEB128(Abbrev->getNumber(), "Abbreviation Code"); - - // Emit the abbreviations data. - Abbrev->Emit(Asm); - } - - // Mark end of abbreviations. - Asm->EmitULEB128(0, "EOM(3)"); - } -} - // Emit the last address of the section and the end of the line matrix. void DwarfDebug::emitEndOfLineMatrix(unsigned SectionEnd) { // Define last address of section. @@ -2032,97 +1705,52 @@ 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 (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"); + AccelNames.FinalizeTable(Asm, "Names"); Asm->OutStreamer.SwitchSection( Asm->getObjFileLowering().getDwarfAccelNamesSection()); MCSymbol *SectionBegin = Asm->GetTempSymbol("names_begin"); Asm->OutStreamer.EmitLabel(SectionBegin); // Emit the full data. - AT.Emit(Asm, SectionBegin, &InfoHolder); + AccelNames.Emit(Asm, SectionBegin, &InfoHolder); } // 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 (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"); + AccelObjC.FinalizeTable(Asm, "ObjC"); Asm->OutStreamer.SwitchSection( Asm->getObjFileLowering().getDwarfAccelObjCSection()); MCSymbol *SectionBegin = Asm->GetTempSymbol("objc_begin"); Asm->OutStreamer.EmitLabel(SectionBegin); // Emit the full data. - AT.Emit(Asm, SectionBegin, &InfoHolder); + AccelObjC.Emit(Asm, SectionBegin, &InfoHolder); } // 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 (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"); + AccelNamespace.FinalizeTable(Asm, "namespac"); Asm->OutStreamer.SwitchSection( Asm->getObjFileLowering().getDwarfAccelNamespaceSection()); MCSymbol *SectionBegin = Asm->GetTempSymbol("namespac_begin"); Asm->OutStreamer.EmitLabel(SectionBegin); // Emit the full data. - AT.Emit(Asm, SectionBegin, &InfoHolder); + AccelNamespace.Emit(Asm, SectionBegin, &InfoHolder); } // 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)); - DwarfAccelTable AT(Atoms); - 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"); + AccelTypes.FinalizeTable(Asm, "types"); Asm->OutStreamer.SwitchSection( Asm->getObjFileLowering().getDwarfAccelTypesSection()); MCSymbol *SectionBegin = Asm->GetTempSymbol("types_begin"); Asm->OutStreamer.EmitLabel(SectionBegin); // Emit the full data. - AT.Emit(Asm, SectionBegin, &InfoHolder); + AccelTypes.Emit(Asm, SectionBegin, &InfoHolder); } // Public name handling. @@ -2148,8 +1776,8 @@ static dwarf::PubIndexEntryDescriptor computeIndexValue(DwarfUnit *CU, // look for that now. DIEValue *SpecVal = Die->findAttribute(dwarf::DW_AT_specification); if (SpecVal) { - DIE *SpecDIE = cast<DIEEntry>(SpecVal)->getEntry(); - if (SpecDIE->findAttribute(dwarf::DW_AT_external)) + DIE &SpecDIE = cast<DIEEntry>(SpecVal)->getEntry(); + if (SpecDIE.findAttribute(dwarf::DW_AT_external)) Linkage = dwarf::GIEL_EXTERNAL; } else if (Die->findAttribute(dwarf::DW_AT_external)) Linkage = dwarf::GIEL_EXTERNAL; @@ -2261,69 +1889,6 @@ void DwarfDebug::emitDebugPubTypes(bool GnuStyle) { emitDebugPubSection(GnuStyle, PSec, "Types", &DwarfUnit::getGlobalTypes); } -// Emit strings into a string section. -void DwarfFile::emitStrings(const MCSection *StrSection, - const MCSection *OffsetSection = NULL, - const MCSymbol *StrSecSym = NULL) { - - 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, const StrPool::value_type *>, 64 > Entries; - - for (const auto &I : StringPool) - Entries.push_back(std::make_pair(I.second.second, &I)); - - array_pod_sort(Entries.begin(), Entries.end()); - - for (const auto &Entry : Entries) { - // Emit a label for reference from debug information entries. - Asm->OutStreamer.EmitLabel(Entry.second->getValue().first); - - // Emit the string itself with a terminating null byte. - 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. - if (OffsetSection) { - Asm->OutStreamer.SwitchSection(OffsetSection); - unsigned offset = 0; - unsigned size = 4; // FIXME: DWARF64 is 8. - for (const auto &Entry : Entries) { - Asm->OutStreamer.EmitIntValue(offset, size); - offset += Entry.second->getKeyLength() + 1; - } - } -} - -// Emit addresses into the section given. -void DwarfFile::emitAddresses(const MCSection *AddrSection) { - - if (AddressPool.empty()) - return; - - // Start the dwarf addr section. - Asm->OutStreamer.SwitchSection(AddrSection); - - // Order the address pool entries by ID - SmallVector<const MCExpr *, 64> Entries(AddressPool.size()); - - 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() { DwarfFile &Holder = useSplitDwarf() ? SkeletonHolder : InfoHolder; @@ -2332,19 +1897,22 @@ void DwarfDebug::emitDebugStr() { void DwarfDebug::emitDebugLocEntry(ByteStreamer &Streamer, const DebugLocEntry &Entry) { - DIVariable DV(Entry.getVariable()); - if (Entry.isInt()) { + assert(Entry.getValues().size() == 1 && + "multi-value entries are not supported yet."); + const DebugLocEntry::Value Value = Entry.getValues()[0]; + DIVariable DV(Value.getVariable()); + if (Value.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()); + Streamer.EmitSLEB128(Value.getInt()); } else { Streamer.EmitInt8(dwarf::DW_OP_constu, "DW_OP_constu"); - Streamer.EmitULEB128(Entry.getInt()); + Streamer.EmitULEB128(Value.getInt()); } - } else if (Entry.isLocation()) { - MachineLocation Loc = Entry.getLoc(); + } else if (Value.isLocation()) { + MachineLocation Loc = Value.getLoc(); if (!DV.hasComplexAddress()) // Regular entry. Asm->EmitDwarfRegOp(Streamer, Loc, DV.isIndirect()); @@ -2443,7 +2011,7 @@ void DwarfDebug::emitDebugLocDWO() { // 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()); + unsigned idx = AddrPool.getIndex(Entry.getBeginSym()); Asm->EmitULEB128(idx); Asm->EmitLabelDifference(Entry.getEndSym(), Entry.getBeginSym(), 4); @@ -2464,7 +2032,7 @@ void DwarfDebug::emitDebugARanges() { Asm->OutStreamer.SwitchSection( Asm->getObjFileLowering().getDwarfARangesSection()); - typedef DenseMap<DwarfCompileUnit *, std::vector<ArangeSpan> > SpansType; + typedef DenseMap<DwarfCompileUnit *, std::vector<ArangeSpan>> SpansType; SpansType Spans; @@ -2502,11 +2070,11 @@ void DwarfDebug::emitDebugARanges() { // If we have no section (e.g. common), just write out // individual spans for each symbol. - if (Section == NULL) { + if (!Section) { for (const SymbolCU &Cur : List) { ArangeSpan Span; Span.Start = Cur.Sym; - Span.End = NULL; + Span.End = nullptr; if (Cur.CU) Spans[Cur.CU].push_back(Span); } @@ -2613,9 +2181,6 @@ void DwarfDebug::emitDebugRanges() { 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. @@ -2626,8 +2191,15 @@ void DwarfDebug::emitDebugRanges() { 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); + if (TheCU->getRanges().size() == 1) { + // Grab the begin symbol from the first range as our base. + const MCSymbol *Base = TheCU->getRanges()[0].getStart(); + Asm->EmitLabelDifference(Begin, Base, Size); + Asm->EmitLabelDifference(End, Base, Size); + } else { + Asm->OutStreamer.EmitSymbolValue(Begin, Size); + Asm->OutStreamer.EmitSymbolValue(End, Size); + } } // And terminate the list with two 0 values. @@ -2656,52 +2228,52 @@ void DwarfDebug::emitDebugRanges() { // DWARF5 Experimental Separate Dwarf emitters. -void DwarfDebug::initSkeletonUnit(const DwarfUnit *U, DIE *Die, - DwarfUnit *NewU) { +void DwarfDebug::initSkeletonUnit(const DwarfUnit &U, DIE &Die, + std::unique_ptr<DwarfUnit> NewU) { NewU->addLocalString(Die, dwarf::DW_AT_GNU_dwo_name, - U->getCUNode().getSplitDebugFilename()); + U.getCUNode().getSplitDebugFilename()); if (!CompilationDir.empty()) NewU->addLocalString(Die, dwarf::DW_AT_comp_dir, CompilationDir); - addGnuPubAttributes(NewU, Die); + addGnuPubAttributes(*NewU, Die); - SkeletonHolder.addUnit(NewU); + SkeletonHolder.addUnit(std::move(NewU)); } // This DIE has the following attributes: DW_AT_comp_dir, DW_AT_stmt_list, // DW_AT_low_pc, DW_AT_high_pc, DW_AT_ranges, DW_AT_dwo_name, DW_AT_dwo_id, // DW_AT_addr_base, DW_AT_ranges_base. -DwarfCompileUnit *DwarfDebug::constructSkeletonCU(const DwarfCompileUnit *CU) { +DwarfCompileUnit &DwarfDebug::constructSkeletonCU(const DwarfCompileUnit &CU) { - 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); + auto OwnedUnit = make_unique<DwarfCompileUnit>( + CU.getUniqueID(), CU.getCUNode(), Asm, this, &SkeletonHolder); + DwarfCompileUnit &NewCU = *OwnedUnit; + NewCU.initSection(Asm->getObjFileLowering().getDwarfInfoSection(), + DwarfInfoSectionSym); - NewCU->initStmtList(DwarfLineSectionSym); + NewCU.initStmtList(DwarfLineSectionSym); - initSkeletonUnit(CU, Die, NewCU); + initSkeletonUnit(CU, NewCU.getUnitDie(), std::move(OwnedUnit)); return NewCU; } // This DIE has the following attributes: DW_AT_comp_dir, DW_AT_dwo_name, // DW_AT_addr_base. -DwarfTypeUnit *DwarfDebug::constructSkeletonTU(DwarfTypeUnit *TU) { +DwarfTypeUnit &DwarfDebug::constructSkeletonTU(DwarfTypeUnit &TU) { DwarfCompileUnit &CU = static_cast<DwarfCompileUnit &>( - *SkeletonHolder.getUnits()[TU->getCU().getUniqueID()]); + *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())); + auto OwnedUnit = make_unique<DwarfTypeUnit>(TU.getUniqueID(), CU, Asm, this, + &SkeletonHolder); + DwarfTypeUnit &NewTU = *OwnedUnit; + NewTU.setTypeSignature(TU.getTypeSignature()); + NewTU.setType(nullptr); + NewTU.initSection( + Asm->getObjFileLowering().getDwarfTypesSection(TU.getTypeSignature())); - initSkeletonUnit(TU, Die, NewTU); + initSkeletonUnit(TU, NewTU.getUnitDie(), std::move(OwnedUnit)); return NewTU; } @@ -2711,7 +2283,7 @@ void DwarfDebug::emitDebugInfoDWO() { assert(useSplitDwarf() && "No split dwarf debug info?"); // 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); + InfoHolder.emitUnits(this, /* AbbrevSymbol */ nullptr); } // Emit the .debug_abbrev.dwo section for separated dwarf. This contains the @@ -2748,14 +2320,25 @@ MCDwarfDwoLineTable *DwarfDebug::getDwoLineTable(const DwarfCompileUnit &CU) { return &SplitTypeUnitFileTable; } +static uint64_t makeTypeSignature(StringRef Identifier) { + 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); + return *reinterpret_cast<support::ulittle64_t *>(Result + 8); +} + void DwarfDebug::addDwarfTypeUnitType(DwarfCompileUnit &CU, - StringRef Identifier, DIE *RefDie, + 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); + // Fast path if we're building some type units and one has already used the + // address pool we know we're going to throw away all this work anyway, so + // don't bother building dependent types. + if (!TypeUnitsUnderConstruction.empty() && AddrPool.hasBeenUsed()) + return; const DwarfTypeUnit *&TU = DwarfTypeUnits[CTy]; if (TU) { @@ -2763,45 +2346,111 @@ void DwarfDebug::addDwarfTypeUnitType(DwarfCompileUnit &CU, 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); + bool TopLevelType = TypeUnitsUnderConstruction.empty(); + AddrPool.resetUsedFlag(); - NewTU->addUInt(UnitDie, dwarf::DW_AT_language, dwarf::DW_FORM_data2, - CU.getLanguage()); + auto OwnedUnit = + make_unique<DwarfTypeUnit>(InfoHolder.getUnits().size(), CU, Asm, this, + &InfoHolder, getDwoLineTable(CU)); + DwarfTypeUnit &NewTU = *OwnedUnit; + DIE &UnitDie = NewTU.getUnitDie(); + TU = &NewTU; + TypeUnitsUnderConstruction.push_back( + std::make_pair(std::move(OwnedUnit), CTy)); - 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.addUInt(UnitDie, dwarf::DW_AT_language, dwarf::DW_FORM_data2, + CU.getLanguage()); - NewTU->setType(NewTU->createTypeDIE(CTy)); + uint64_t Signature = makeTypeSignature(Identifier); + NewTU.setTypeSignature(Signature); - NewTU->initSection( + if (!useSplitDwarf()) + CU.applyStmtList(UnitDie); + + // FIXME: Skip using COMDAT groups for type units in the .dwo file once tools + // such as DWP ( http://gcc.gnu.org/wiki/DebugFissionDWP ) can cope with it. + NewTU.initSection( useSplitDwarf() ? Asm->getObjFileLowering().getDwarfTypesDWOSection(Signature) : Asm->getObjFileLowering().getDwarfTypesSection(Signature)); - CU.addDIETypeSignature(RefDie, *NewTU); + NewTU.setType(NewTU.createTypeDIE(CTy)); + + if (TopLevelType) { + auto TypeUnitsToAdd = std::move(TypeUnitsUnderConstruction); + TypeUnitsUnderConstruction.clear(); + + // Types referencing entries in the address table cannot be placed in type + // units. + if (AddrPool.hasBeenUsed()) { + + // Remove all the types built while building this type. + // This is pessimistic as some of these types might not be dependent on + // the type that used an address. + for (const auto &TU : TypeUnitsToAdd) + DwarfTypeUnits.erase(TU.second); + + // Construct this type in the CU directly. + // This is inefficient because all the dependent types will be rebuilt + // from scratch, including building them in type units, discovering that + // they depend on addresses, throwing them out and rebuilding them. + CU.constructTypeDIE(RefDie, CTy); + return; + } + + // If the type wasn't dependent on fission addresses, finish adding the type + // and all its dependent types. + for (auto &TU : TypeUnitsToAdd) { + if (useSplitDwarf()) + TU.first->setSkeleton(constructSkeletonTU(*TU.first)); + InfoHolder.addUnit(std::move(TU.first)); + } + } + CU.addDIETypeSignature(RefDie, NewTU); } -void DwarfDebug::attachLowHighPC(DwarfCompileUnit *Unit, DIE *D, +void DwarfDebug::attachLowHighPC(DwarfCompileUnit &Unit, DIE &D, MCSymbol *Begin, MCSymbol *End) { - Unit->addLabelAddress(D, dwarf::DW_AT_low_pc, Begin); + assert(Begin && "Begin label should not be null!"); + assert(End && "End label should not be null!"); + assert(Begin->isDefined() && "Invalid starting label"); + assert(End->isDefined() && "Invalid end label"); + + Unit.addLabelAddress(D, dwarf::DW_AT_low_pc, Begin); if (DwarfVersion < 4) - Unit->addLabelAddress(D, dwarf::DW_AT_high_pc, End); + Unit.addLabelAddress(D, dwarf::DW_AT_high_pc, End); else - Unit->addLabelDelta(D, dwarf::DW_AT_high_pc, End, Begin); + Unit.addLabelDelta(D, dwarf::DW_AT_high_pc, End, Begin); +} + +// Accelerator table mutators - add each name along with its companion +// DIE to the proper table while ensuring that the name that we're going +// to reference is in the string table. We do this since the names we +// add may not only be identical to the names in the DIE. +void DwarfDebug::addAccelName(StringRef Name, const DIE &Die) { + if (!useDwarfAccelTables()) + return; + AccelNames.AddName(Name, InfoHolder.getStringPool().getSymbol(*Asm, Name), + &Die); +} + +void DwarfDebug::addAccelObjC(StringRef Name, const DIE &Die) { + if (!useDwarfAccelTables()) + return; + AccelObjC.AddName(Name, InfoHolder.getStringPool().getSymbol(*Asm, Name), + &Die); +} + +void DwarfDebug::addAccelNamespace(StringRef Name, const DIE &Die) { + if (!useDwarfAccelTables()) + return; + AccelNamespace.AddName(Name, InfoHolder.getStringPool().getSymbol(*Asm, Name), + &Die); +} + +void DwarfDebug::addAccelType(StringRef Name, const DIE &Die, char Flags) { + if (!useDwarfAccelTables()) + return; + AccelTypes.AddName(Name, InfoHolder.getStringPool().getSymbol(*Asm, Name), + &Die); } diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.h b/lib/CodeGen/AsmPrinter/DwarfDebug.h index da708f5..2f5abc8 100644 --- a/lib/CodeGen/AsmPrinter/DwarfDebug.h +++ b/lib/CodeGen/AsmPrinter/DwarfDebug.h @@ -14,10 +14,13 @@ #ifndef CODEGEN_ASMPRINTER_DWARFDEBUG_H__ #define CODEGEN_ASMPRINTER_DWARFDEBUG_H__ +#include "DwarfFile.h" #include "AsmPrinterHandler.h" #include "DIE.h" +#include "DbgValueHistoryCalculator.h" #include "DebugLocEntry.h" #include "DebugLocList.h" +#include "DwarfAccelTable.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/MapVector.h" #include "llvm/ADT/SmallPtrSet.h" @@ -30,6 +33,8 @@ #include "llvm/MC/MCDwarf.h" #include "llvm/Support/Allocator.h" +#include <memory> + namespace llvm { class AsmPrinter; @@ -74,12 +79,12 @@ class DbgVariable { 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(nullptr), DotDebugLocOffset(~0U), AbsVar(AV), + MInsn(nullptr), FrameIndex(~0), DD(DD) {} // Accessors. DIVariable getVariable() const { return Var; } - void setDIE(DIE *D) { TheDIE = D; } + void setDIE(DIE &D) { TheDIE = &D; } DIE *getDIE() const { return TheDIE; } void setDotDebugLocOffset(unsigned O) { DotDebugLocOffset = O; } unsigned getDotDebugLocOffset() const { return DotDebugLocOffset; } @@ -90,7 +95,7 @@ public: int getFrameIndex() const { return FrameIndex; } void setFrameIndex(int FI) { FrameIndex = FI; } // Translate tag to proper Dwarf tag. - uint16_t getTag() const { + dwarf::Tag getTag() const { if (Var.getTag() == dwarf::DW_TAG_arg_variable) return dwarf::DW_TAG_formal_parameter; @@ -131,99 +136,6 @@ private: template <typename T> T resolve(DIRef<T> Ref) const; }; -/// \brief Collects and handles information specific to a particular -/// 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; - - // A list of all the unique abbreviations in use. - std::vector<DIEAbbrev *> Abbreviations; - - // A pointer to all units in the section. - 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; - 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 MCSymbol *, AddressPoolEntry> AddrPool; - AddrPool AddressPool; - unsigned NextAddrPoolNumber; - -public: - 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); - - /// \brief Compute the size and offset of all the DIEs. - void computeSizeAndOffsets(); - - /// \brief Define a unique number for the abbreviation. - void assignAbbrevNumber(DIEAbbrev &Abbrev); - - /// \brief Add a unit to the list of CUs. - 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 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, - const MCSymbol *StrSecSym); - - /// \brief Emit all of the addresses to the section given. - void emitAddresses(const MCSection *AddrSection); - - /// \brief Returns the entry into the start of the pool. - MCSymbol *getStringPoolSym(); - - /// \brief Returns an entry into the string pool with the given - /// string text. - MCSymbol *getStringPoolEntry(StringRef Str); - - /// \brief Returns the index into the string pool with the given - /// string text. - unsigned getStringPoolIndex(StringRef Str); - - /// \brief Returns the string pool. - StrPool *getStringPool() { return &StringPool; } - - /// \brief Returns the index into the address pool with the given - /// label/symbol. - unsigned getAddrPoolIndex(const MCSymbol *Sym, bool TLS = false); - - /// \brief Returns the address pool. - AddrPool *getAddrPool() { return &AddressPool; } -}; /// \brief Helper used to pair up a symbol and its DWARF compile unit. struct SymbolCU { @@ -287,7 +199,7 @@ class DwarfDebug : public AsmPrinterHandler { ScopeVariablesMap ScopeVariables; // Collection of abstract variables. - DenseMap<const MDNode *, DbgVariable *> AbstractVariables; + DenseMap<const MDNode *, std::unique_ptr<DbgVariable>> AbstractVariables; // Collection of DebugLocEntry. Stored in a linked list so that DIELocLists // can refer to them in spite of insertions into this list. @@ -307,15 +219,8 @@ class DwarfDebug : public AsmPrinterHandler { // Maps instruction with label emitted after instruction. DenseMap<const MachineInstr *, MCSymbol *> LabelsAfterInsn; - // Every user variable mentioned by a DBG_VALUE instruction in order of - // appearance. - 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; + // History of DBG_VALUE and clobber instructions for each user variable. + // Variables are listed in order of appearance. DbgValueHistoryMap DbgValues; // Previous instruction's location information. This is used to determine @@ -373,6 +278,8 @@ class DwarfDebug : public AsmPrinterHandler { // them. DenseMap<const MDNode *, const DwarfTypeUnit *> DwarfTypeUnits; + SmallVector<std::pair<std::unique_ptr<DwarfTypeUnit>, DICompositeType>, 1> TypeUnitsUnderConstruction; + // Whether to emit the pubnames/pubtypes sections. bool HasDwarfPubSections; @@ -411,22 +318,30 @@ class DwarfDebug : public AsmPrinterHandler { // True iff there are multiple CUs in this module. bool SingleCU; + AddressPool AddrPool; + + DwarfAccelTable AccelNames; + DwarfAccelTable AccelObjC; + DwarfAccelTable AccelNamespace; + DwarfAccelTable AccelTypes; + MCDwarfDwoLineTable *getDwoLineTable(const DwarfCompileUnit &); void addScopeVariable(LexicalScope *LS, DbgVariable *Var); - const SmallVectorImpl<DwarfUnit *> &getUnits() { + const SmallVectorImpl<std::unique_ptr<DwarfUnit>> &getUnits() { return InfoHolder.getUnits(); } /// \brief Find abstract variable associated with Var. DbgVariable *findAbstractVariable(DIVariable &Var, DebugLoc Loc); + DbgVariable *findAbstractVariable(DIVariable &Var, const MDNode *Scope); /// \brief 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 *updateSubprogramScopeDIE(DwarfCompileUnit *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. @@ -434,22 +349,33 @@ class DwarfDebug : public AsmPrinterHandler { /// \brief A helper function to construct a RangeSpanList for a given /// lexical scope. - void addScopeRangeList(DwarfCompileUnit *TheCU, DIE *ScopeDIE, + 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(DwarfCompileUnit *TheCU, LexicalScope *Scope); + std::unique_ptr<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(DwarfCompileUnit *TheCU, LexicalScope *Scope); + std::unique_ptr<DIE> constructInlinedScopeDIE(DwarfCompileUnit &TheCU, + LexicalScope *Scope); /// \brief Construct a DIE for this scope. - DIE *constructScopeDIE(DwarfCompileUnit *TheCU, LexicalScope *Scope); + std::unique_ptr<DIE> constructScopeDIE(DwarfCompileUnit &TheCU, + LexicalScope *Scope); + void createAndAddScopeChildren(DwarfCompileUnit &TheCU, LexicalScope *Scope, + DIE &ScopeDIE); + /// \brief Construct a DIE for this abstract scope. + void constructAbstractSubprogramScopeDIE(DwarfCompileUnit &TheCU, + LexicalScope *Scope); + /// \brief Construct a DIE for this subprogram scope. + DIE &constructSubprogramScopeDIE(DwarfCompileUnit &TheCU, + LexicalScope *Scope); /// A helper function to create children of a Scope DIE. - DIE *createScopeChildrenDIE(DwarfCompileUnit *TheCU, LexicalScope *Scope, - SmallVectorImpl<DIE *> &Children); + DIE *createScopeChildrenDIE(DwarfCompileUnit &TheCU, LexicalScope *Scope, + SmallVectorImpl<std::unique_ptr<DIE>> &Children); /// \brief Emit initial Dwarf sections with a label at the start of each one. void emitSectionLabels(); @@ -460,12 +386,11 @@ class DwarfDebug : public AsmPrinterHandler { /// \brief Compute the size and offset of all the DIEs. void computeSizeAndOffsets(); - /// \brief Attach DW_AT_inline attribute with inlined subprogram DIEs. - void computeInlinedDIEs(); - /// \brief Collect info for variables that were optimized out. void collectDeadVariables(); + void finishSubprogramDefinitions(); + /// \brief Finish off debug information after all functions have been /// processed. void finalizeModuleInfo(); @@ -535,15 +460,16 @@ class DwarfDebug : public AsmPrinterHandler { /// DWARF 5 Experimental Split Dwarf Emitters /// \brief Initialize common features of skeleton units. - void initSkeletonUnit(const DwarfUnit *U, DIE *Die, DwarfUnit *NewU); + void initSkeletonUnit(const DwarfUnit &U, DIE &Die, + std::unique_ptr<DwarfUnit> NewU); /// \brief Construct the split debug info compile unit for the debug info /// section. - DwarfCompileUnit *constructSkeletonCU(const DwarfCompileUnit *CU); + DwarfCompileUnit &constructSkeletonCU(const DwarfCompileUnit &CU); /// \brief Construct the split debug info compile unit for the debug info /// section. - DwarfTypeUnit *constructSkeletonTU(DwarfTypeUnit *TU); + DwarfTypeUnit &constructSkeletonTU(DwarfTypeUnit &TU); /// \brief Emit the debug info dwo section. void emitDebugInfoDWO(); @@ -559,25 +485,22 @@ class DwarfDebug : public AsmPrinterHandler { /// 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; + void addGnuPubAttributes(DwarfUnit &U, DIE &D) const; /// \brief Create new DwarfCompileUnit for the given metadata node with tag /// DW_TAG_compile_unit. - DwarfCompileUnit *constructDwarfCompileUnit(DICompileUnit DIUnit); - - /// \brief Construct subprogram DIE. - void constructSubprogramDIE(DwarfCompileUnit *TheCU, const MDNode *N); + DwarfCompileUnit &constructDwarfCompileUnit(DICompileUnit DIUnit); /// \brief Construct imported_module or imported_declaration DIE. - void constructImportedEntityDIE(DwarfCompileUnit *TheCU, const MDNode *N); + void constructImportedEntityDIE(DwarfCompileUnit &TheCU, const MDNode *N); /// \brief Construct import_module DIE. - void constructImportedEntityDIE(DwarfCompileUnit *TheCU, const MDNode *N, - DIE *Context); + void constructImportedEntityDIE(DwarfCompileUnit &TheCU, const MDNode *N, + DIE &Context); /// \brief Construct import_module DIE. - void constructImportedEntityDIE(DwarfCompileUnit *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 @@ -602,7 +525,7 @@ class DwarfDebug : public AsmPrinterHandler { /// \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, nullptr)); } /// \brief Return Label preceding the instruction. @@ -610,13 +533,15 @@ class DwarfDebug : public AsmPrinterHandler { /// \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, nullptr)); } /// \brief Return Label immediately following the instruction. MCSymbol *getLabelAfterInsn(const MachineInstr *MI); - void attachLowHighPC(DwarfCompileUnit *Unit, DIE *D, MCSymbol *Begin, + void attachRangesOrLowHighPC(DwarfCompileUnit &Unit, DIE &D, + const SmallVectorImpl<InsnRange> &Ranges); + void attachLowHighPC(DwarfCompileUnit &Unit, DIE &D, MCSymbol *Begin, MCSymbol *End); public: @@ -625,6 +550,8 @@ public: // DwarfDebug(AsmPrinter *A, Module *M); + ~DwarfDebug() override; + void insertDIE(const MDNode *TypeMD, DIE *Die) { MDTypeNodeToDieMap.insert(std::make_pair(TypeMD, Die)); } @@ -654,7 +581,7 @@ public: /// \brief Add a DIE to the set of types that we're going to pull into /// type units. void addDwarfTypeUnitType(DwarfCompileUnit &CU, StringRef Identifier, - DIE *Die, DICompositeType CTy); + 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); } @@ -666,7 +593,7 @@ public: } /// \brief Recursively Emits a debug information entry. - void emitDIE(DIE *Die); + void emitDIE(DIE &Die); // Experimental DWARF5 features. @@ -720,6 +647,18 @@ public: /// isSubprogramContext - Return true if Context is either a subprogram /// or another context nested inside a subprogram. bool isSubprogramContext(const MDNode *Context); + + void addSubprogramNames(DISubprogram SP, DIE &Die); + + AddressPool &getAddressPool() { return AddrPool; } + + void addAccelName(StringRef Name, const DIE &Die); + + void addAccelObjC(StringRef Name, const DIE &Die); + + void addAccelNamespace(StringRef Name, const DIE &Die); + + void addAccelType(StringRef Name, const DIE &Die, char Flags); }; } // End of namespace llvm diff --git a/lib/CodeGen/AsmPrinter/DwarfException.cpp b/lib/CodeGen/AsmPrinter/DwarfException.cpp index 113a9e4..3a12c73 100644 --- a/lib/CodeGen/AsmPrinter/DwarfException.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfException.cpp @@ -103,7 +103,7 @@ ComputeActionsTable(const SmallVectorImpl<const LandingPadInfo*> &LandingPads, int FirstAction = 0; unsigned SizeActions = 0; - const LandingPadInfo *PrevLPI = 0; + const LandingPadInfo *PrevLPI = nullptr; for (SmallVectorImpl<const LandingPadInfo *>::const_iterator I = LandingPads.begin(), E = LandingPads.end(); I != E; ++I) { @@ -181,7 +181,7 @@ bool DwarfException::CallToNoUnwindFunction(const MachineInstr *MI) { if (!MO.isGlobal()) continue; const Function *F = dyn_cast<Function>(MO.getGlobal()); - if (F == 0) continue; + if (!F) continue; if (SawFunc) { // Be conservative. If we have more than one function operand for this @@ -214,7 +214,7 @@ ComputeCallSiteTable(SmallVectorImpl<CallSiteEntry> &CallSites, const SmallVectorImpl<const LandingPadInfo *> &LandingPads, const SmallVectorImpl<unsigned> &FirstActions) { // The end label of the previous invoke or nounwind try-range. - MCSymbol *LastLabel = 0; + MCSymbol *LastLabel = nullptr; // Whether there is a potentially throwing instruction (currently this means // an ordinary call) between the end of the previous try-range and now. @@ -224,18 +224,16 @@ ComputeCallSiteTable(SmallVectorImpl<CallSiteEntry> &CallSites, bool PreviousIsInvoke = false; // Visit all instructions in order of address. - for (MachineFunction::const_iterator I = Asm->MF->begin(), E = Asm->MF->end(); - I != E; ++I) { - for (MachineBasicBlock::const_iterator MI = I->begin(), E = I->end(); - MI != E; ++MI) { - if (!MI->isEHLabel()) { - if (MI->isCall()) - SawPotentiallyThrowing |= !CallToNoUnwindFunction(MI); + for (const auto &MBB : *Asm->MF) { + for (const auto &MI : MBB) { + if (!MI.isEHLabel()) { + if (MI.isCall()) + SawPotentiallyThrowing |= !CallToNoUnwindFunction(&MI); continue; } // End of the previous try-range? - MCSymbol *BeginLabel = MI->getOperand(0).getMCSymbol(); + MCSymbol *BeginLabel = MI.getOperand(0).getMCSymbol(); if (BeginLabel == LastLabel) SawPotentiallyThrowing = false; @@ -255,7 +253,7 @@ ComputeCallSiteTable(SmallVectorImpl<CallSiteEntry> &CallSites, // create a call-site entry with no landing pad for the region between the // try-ranges. if (SawPotentiallyThrowing && Asm->MAI->isExceptionHandlingDwarf()) { - CallSiteEntry Site = { LastLabel, BeginLabel, 0, 0 }; + CallSiteEntry Site = { LastLabel, BeginLabel, nullptr, 0 }; CallSites.push_back(Site); PreviousIsInvoke = false; } @@ -305,7 +303,7 @@ ComputeCallSiteTable(SmallVectorImpl<CallSiteEntry> &CallSites, // function may throw, create a call-site entry with no landing pad for the // region following the try-range. if (SawPotentiallyThrowing && Asm->MAI->isExceptionHandlingDwarf()) { - CallSiteEntry Site = { LastLabel, 0, 0, 0 }; + CallSiteEntry Site = { LastLabel, nullptr, nullptr, 0 }; CallSites.push_back(Site); } } @@ -571,10 +569,10 @@ void DwarfException::EmitExceptionTable() { Asm->GetTempSymbol("eh_func_begin", Asm->getFunctionNumber()); MCSymbol *BeginLabel = S.BeginLabel; - if (BeginLabel == 0) + if (!BeginLabel) BeginLabel = EHFuncBeginSym; MCSymbol *EndLabel = S.EndLabel; - if (EndLabel == 0) + if (!EndLabel) EndLabel = Asm->GetTempSymbol("eh_func_end", Asm->getFunctionNumber()); diff --git a/lib/CodeGen/AsmPrinter/DwarfFile.cpp b/lib/CodeGen/AsmPrinter/DwarfFile.cpp new file mode 100644 index 0000000..737ee54 --- /dev/null +++ b/lib/CodeGen/AsmPrinter/DwarfFile.cpp @@ -0,0 +1,156 @@ +//===-- llvm/CodeGen/DwarfFile.cpp - Dwarf Debug Framework ----------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "DwarfFile.h" + +#include "DwarfDebug.h" +#include "DwarfUnit.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/Support/LEB128.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/Target/TargetLoweringObjectFile.h" + +namespace llvm { +DwarfFile::DwarfFile(AsmPrinter *AP, StringRef Pref, BumpPtrAllocator &DA) + : Asm(AP), StrPool(DA, *Asm, Pref) {} + +DwarfFile::~DwarfFile() {} + +// Define a unique number for the abbreviation. +// +void DwarfFile::assignAbbrevNumber(DIEAbbrev &Abbrev) { + // Check the set for priors. + DIEAbbrev *InSet = AbbreviationsSet.GetOrInsertNode(&Abbrev); + + // If it's newly added. + if (InSet == &Abbrev) { + // Add to abbreviation list. + Abbreviations.push_back(&Abbrev); + + // Assign the vector position + 1 as its number. + Abbrev.setNumber(Abbreviations.size()); + } else { + // Assign existing abbreviation number. + Abbrev.setNumber(InSet->getNumber()); + } +} + +void DwarfFile::addUnit(std::unique_ptr<DwarfUnit> U) { + CUs.push_back(std::move(U)); +} + +// Emit the various dwarf units to the unit section USection with +// the abbreviations going into ASection. +void DwarfFile::emitUnits(DwarfDebug *DD, const MCSymbol *ASectionSym) { + for (const auto &TheU : CUs) { + DIE &Die = TheU->getUnitDie(); + const MCSection *USection = TheU->getSection(); + Asm->OutStreamer.SwitchSection(USection); + + // Emit the compile units header. + Asm->OutStreamer.EmitLabel(TheU->getLabelBegin()); + + // Emit size of content not including length itself + Asm->OutStreamer.AddComment("Length of Unit"); + Asm->EmitInt32(TheU->getHeaderSize() + Die.getSize()); + + TheU->emitHeader(ASectionSym); + + DD->emitDIE(Die); + Asm->OutStreamer.EmitLabel(TheU->getLabelEnd()); + } +} +// Compute the size and offset for each DIE. +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 (const auto &TheU : CUs) { + TheU->setDebugInfoOffset(SecOffset); + + // CU-relative offset is reset to 0 here. + 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(TheU->getUnitDie(), Offset); + SecOffset += EndOffset; + } +} +// 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 DwarfFile::computeSizeAndOffset(DIE &Die, unsigned Offset) { + // Record the abbreviation. + assignAbbrevNumber(Die.getAbbrev()); + + // Get the abbreviation for this DIE. + const DIEAbbrev &Abbrev = Die.getAbbrev(); + + // Set DIE offset + Die.setOffset(Offset); + + // Start the size with the size of abbreviation code. + Offset += getULEB128Size(Die.getAbbrevNumber()); + + 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 auto &Children = Die.getChildren(); + + // Size the DIE children if any. + if (!Children.empty()) { + assert(Abbrev.hasChildren() && "Children flag not set"); + + for (auto &Child : Children) + Offset = computeSizeAndOffset(*Child, Offset); + + // End of children marker. + Offset += sizeof(int8_t); + } + + Die.setSize(Offset - Die.getOffset()); + return Offset; +} +void DwarfFile::emitAbbrevs(const MCSection *Section) { + // Check to see if it is worth the effort. + if (!Abbreviations.empty()) { + // Start the debug abbrev section. + Asm->OutStreamer.SwitchSection(Section); + + // For each abbrevation. + for (const DIEAbbrev *Abbrev : Abbreviations) { + // Emit the abbrevations code (base 1 index.) + Asm->EmitULEB128(Abbrev->getNumber(), "Abbreviation Code"); + + // Emit the abbreviations data. + Abbrev->Emit(Asm); + } + + // Mark end of abbreviations. + Asm->EmitULEB128(0, "EOM(3)"); + } +} + +// Emit strings into a string section. +void DwarfFile::emitStrings(const MCSection *StrSection, + const MCSection *OffsetSection, + const MCSymbol *StrSecSym) { + StrPool.emit(*Asm, StrSection, OffsetSection, StrSecSym); +} +} diff --git a/lib/CodeGen/AsmPrinter/DwarfFile.h b/lib/CodeGen/AsmPrinter/DwarfFile.h new file mode 100644 index 0000000..3985eb2 --- /dev/null +++ b/lib/CodeGen/AsmPrinter/DwarfFile.h @@ -0,0 +1,84 @@ +//===-- llvm/CodeGen/DwarfFile.h - Dwarf Debug Framework -------*- C++ -*--===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef CODEGEN_ASMPRINTER_DWARFFILE_H__ +#define CODEGEN_ASMPRINTER_DWARFFILE_H__ + +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/FoldingSet.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/Support/Allocator.h" +#include "AddressPool.h" +#include "DwarfStringPool.h" + +#include <vector> +#include <string> +#include <memory> + +namespace llvm { +class AsmPrinter; +class DwarfUnit; +class DIEAbbrev; +class MCSymbol; +class DIE; +class StringRef; +class DwarfDebug; +class MCSection; +class DwarfFile { + // Target of Dwarf emission, used for sizing of abbreviations. + AsmPrinter *Asm; + + // Used to uniquely define abbreviations. + FoldingSet<DIEAbbrev> AbbreviationsSet; + + // A list of all the unique abbreviations in use. + std::vector<DIEAbbrev *> Abbreviations; + + // A pointer to all units in the section. + SmallVector<std::unique_ptr<DwarfUnit>, 1> CUs; + + DwarfStringPool StrPool; + +public: + DwarfFile(AsmPrinter *AP, StringRef Pref, BumpPtrAllocator &DA); + + ~DwarfFile(); + + const SmallVectorImpl<std::unique_ptr<DwarfUnit>> &getUnits() { return CUs; } + + /// \brief Compute the size and offset of a DIE given an incoming Offset. + unsigned computeSizeAndOffset(DIE &Die, unsigned Offset); + + /// \brief Compute the size and offset of all the DIEs. + void computeSizeAndOffsets(); + + /// \brief Define a unique number for the abbreviation. + void assignAbbrevNumber(DIEAbbrev &Abbrev); + + /// \brief Add a unit to the list of CUs. + void addUnit(std::unique_ptr<DwarfUnit> U); + + /// \brief Emit all of the units to the section listed with the given + /// abbreviation section. + 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 = nullptr, + const MCSymbol *StrSecSym = nullptr); + + /// \brief Returns the string pool. + DwarfStringPool &getStringPool() { return StrPool; } +}; +} +#endif diff --git a/lib/CodeGen/AsmPrinter/DwarfStringPool.cpp b/lib/CodeGen/AsmPrinter/DwarfStringPool.cpp new file mode 100644 index 0000000..72cab60 --- /dev/null +++ b/lib/CodeGen/AsmPrinter/DwarfStringPool.cpp @@ -0,0 +1,74 @@ +//===-- llvm/CodeGen/DwarfStringPool.cpp - Dwarf Debug Framework ----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "DwarfStringPool.h" +#include "llvm/MC/MCStreamer.h" + +using namespace llvm; + +MCSymbol *DwarfStringPool::getSectionSymbol() { return SectionSymbol; } + +static std::pair<MCSymbol *, unsigned> & +getEntry(AsmPrinter &Asm, + StringMap<std::pair<MCSymbol *, unsigned>, BumpPtrAllocator &> &Pool, + StringRef Prefix, StringRef Str) { + std::pair<MCSymbol *, unsigned> &Entry = + Pool.GetOrCreateValue(Str).getValue(); + if (!Entry.first) { + Entry.second = Pool.size() - 1; + Entry.first = Asm.GetTempSymbol(Prefix, Entry.second); + } + return Entry; +} + +MCSymbol *DwarfStringPool::getSymbol(AsmPrinter &Asm, StringRef Str) { + return getEntry(Asm, Pool, Prefix, Str).first; +} + +unsigned DwarfStringPool::getIndex(AsmPrinter &Asm, StringRef Str) { + return getEntry(Asm, Pool, Prefix, Str).second; +} + +void DwarfStringPool::emit(AsmPrinter &Asm, const MCSection *StrSection, + const MCSection *OffsetSection, + const MCSymbol *StrSecSym) { + if (Pool.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<const StringMapEntry<std::pair<MCSymbol *, unsigned>> *, 64> + Entries(Pool.size()); + + for (const auto &E : Pool) + Entries[E.getValue().second] = &E; + + for (const auto &Entry : Entries) { + // Emit a label for reference from debug information entries. + Asm.OutStreamer.EmitLabel(Entry->getValue().first); + + // Emit the string itself with a terminating null byte. + Asm.OutStreamer.EmitBytes( + StringRef(Entry->getKeyData(), Entry->getKeyLength() + 1)); + } + + // If we've got an offset section go ahead and emit that now as well. + if (OffsetSection) { + Asm.OutStreamer.SwitchSection(OffsetSection); + unsigned offset = 0; + unsigned size = 4; // FIXME: DWARF64 is 8. + for (const auto &Entry : Entries) { + Asm.OutStreamer.EmitIntValue(offset, size); + offset += Entry->getKeyLength() + 1; + } + } +} diff --git a/lib/CodeGen/AsmPrinter/DwarfStringPool.h b/lib/CodeGen/AsmPrinter/DwarfStringPool.h new file mode 100644 index 0000000..c1615fb --- /dev/null +++ b/lib/CodeGen/AsmPrinter/DwarfStringPool.h @@ -0,0 +1,55 @@ +//===-- llvm/CodeGen/DwarfStringPool.h - Dwarf Debug Framework -*- C++ -*--===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef CODEGEN_ASMPRINTER_STRINGPOOL_H__ +#define CODEGEN_ASMPRINTER_STRINGPOOL_H__ + +#include "llvm/ADT/StringMap.h" +#include "llvm/CodeGen/AsmPrinter.h" +#include "llvm/Support/Allocator.h" + +#include <utility> + +namespace llvm { + +class MCSymbol; +class MCSection; +class StringRef; + +// Collection of strings for this unit and assorted symbols. +// A String->Symbol mapping of strings used by indirect +// references. +class DwarfStringPool { + StringMap<std::pair<MCSymbol *, unsigned>, BumpPtrAllocator &> Pool; + StringRef Prefix; + MCSymbol *SectionSymbol; + +public: + DwarfStringPool(BumpPtrAllocator &A, AsmPrinter &Asm, StringRef Prefix) + : Pool(A), Prefix(Prefix), SectionSymbol(Asm.GetTempSymbol(Prefix)) {} + + void emit(AsmPrinter &Asm, const MCSection *StrSection, + const MCSection *OffsetSection = nullptr, + const MCSymbol *StrSecSym = nullptr); + + /// \brief Returns the entry into the start of the pool. + MCSymbol *getSectionSymbol(); + + /// \brief Returns an entry into the string pool with the given + /// string text. + MCSymbol *getSymbol(AsmPrinter &Asm, StringRef Str); + + /// \brief Returns the index into the string pool with the given + /// string text. + unsigned getIndex(AsmPrinter &Asm, StringRef Str); + + bool empty() const { return Pool.empty(); } +}; +} +#endif diff --git a/lib/CodeGen/AsmPrinter/DwarfUnit.cpp b/lib/CodeGen/AsmPrinter/DwarfUnit.cpp index 82e9bb0..a70c0f7 100644 --- a/lib/CodeGen/AsmPrinter/DwarfUnit.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfUnit.cpp @@ -11,8 +11,6 @@ // //===----------------------------------------------------------------------===// -#define DEBUG_TYPE "dwarfdebug" - #include "DwarfUnit.h" #include "DwarfAccelTable.h" #include "DwarfDebug.h" @@ -35,33 +33,38 @@ using namespace llvm; +#define DEBUG_TYPE "dwarfdebug" + static cl::opt<bool> GenerateDwarfTypeUnits("generate-type-units", cl::Hidden, cl::desc("Generate DWARF4 type units."), cl::init(false)); /// 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) { +DwarfUnit::DwarfUnit(unsigned UID, dwarf::Tag UnitTag, DICompileUnit Node, + AsmPrinter *A, DwarfDebug *DW, DwarfFile *DWU) + : UniqueID(UID), CUNode(Node), UnitDie(UnitTag), DebugInfoOffset(0), Asm(A), + DD(DW), DU(DWU), IndexTyDie(nullptr), Section(nullptr), + Skeleton(nullptr) { + assert(UnitTag == dwarf::DW_TAG_compile_unit || + UnitTag == dwarf::DW_TAG_type_unit); DIEIntegerOne = new (DIEValueAllocator) DIEInteger(1); } -DwarfCompileUnit::DwarfCompileUnit(unsigned UID, DIE *D, DICompileUnit Node, +DwarfCompileUnit::DwarfCompileUnit(unsigned UID, DICompileUnit Node, AsmPrinter *A, DwarfDebug *DW, DwarfFile *DWU) - : DwarfUnit(UID, D, Node, A, DW, DWU) { - insertDIE(Node, D); + : DwarfUnit(UID, dwarf::DW_TAG_compile_unit, Node, A, DW, DWU) { + insertDIE(Node, &getUnitDie()); } -DwarfTypeUnit::DwarfTypeUnit(unsigned UID, DIE *D, DwarfCompileUnit &CU, - AsmPrinter *A, DwarfDebug *DW, DwarfFile *DWU, +DwarfTypeUnit::DwarfTypeUnit(unsigned UID, DwarfCompileUnit &CU, AsmPrinter *A, + DwarfDebug *DW, DwarfFile *DWU, MCDwarfDwoLineTable *SplitLineTable) - : DwarfUnit(UID, D, CU.getCUNode(), A, DW, DWU), CU(CU), - SplitLineTable(SplitLineTable) { + : DwarfUnit(UID, dwarf::DW_TAG_type_unit, CU.getCUNode(), A, DW, DWU), + CU(CU), SplitLineTable(SplitLineTable) { if (SplitLineTable) - addSectionOffset(UnitDie.get(), dwarf::DW_AT_stmt_list, 0); + addSectionOffset(UnitDie, dwarf::DW_AT_stmt_list, 0); } /// ~Unit - Destructor for compile unit. @@ -74,7 +77,7 @@ DwarfUnit::~DwarfUnit() { /// createDIEEntry - Creates a new DIEEntry to be a proxy for a debug /// information entry. -DIEEntry *DwarfUnit::createDIEEntry(DIE *Entry) { +DIEEntry *DwarfUnit::createDIEEntry(DIE &Entry) { DIEEntry *Value = new (DIEValueAllocator) DIEEntry(Entry); return Value; } @@ -159,39 +162,39 @@ void DwarfUnit::insertDIE(DIDescriptor Desc, DIE *D) { } /// addFlag - Add a flag that is true. -void DwarfUnit::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); + Die.addValue(Attribute, dwarf::DW_FORM_flag_present, DIEIntegerOne); else - Die->addValue(Attribute, dwarf::DW_FORM_flag, DIEIntegerOne); + Die.addValue(Attribute, dwarf::DW_FORM_flag, DIEIntegerOne); } /// addUInt - Add an unsigned integer attribute data and value. /// -void DwarfUnit::addUInt(DIE *Die, dwarf::Attribute Attribute, +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) DIEInteger(Integer); - Die->addValue(Attribute, *Form, Value); + Die.addValue(Attribute, *Form, Value); } -void DwarfUnit::addUInt(DIE *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 DwarfUnit::addSInt(DIE *Die, dwarf::Attribute Attribute, +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); + Die.addValue(Attribute, *Form, Value); } -void DwarfUnit::addSInt(DIELoc *Die, Optional<dwarf::Form> Form, +void DwarfUnit::addSInt(DIELoc &Die, Optional<dwarf::Form> Form, int64_t Integer) { addSInt(Die, (dwarf::Attribute)0, Form, Integer); } @@ -201,66 +204,66 @@ void DwarfUnit::addSInt(DIELoc *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 DwarfUnit::addString(DIE *Die, dwarf::Attribute Attribute, +void DwarfUnit::addString(DIE &Die, dwarf::Attribute Attribute, StringRef String) { if (!DD->useSplitDwarf()) return addLocalString(Die, Attribute, String); - unsigned idx = DU->getStringPoolIndex(String); + unsigned idx = DU->getStringPool().getIndex(*Asm, String); DIEValue *Value = new (DIEValueAllocator) DIEInteger(idx); DIEValue *Str = new (DIEValueAllocator) DIEString(Value, String); - Die->addValue(Attribute, dwarf::DW_FORM_GNU_str_index, 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 DwarfUnit::addLocalString(DIE *Die, dwarf::Attribute Attribute, +void DwarfUnit::addLocalString(DIE &Die, dwarf::Attribute Attribute, StringRef String) { - MCSymbol *Symb = DU->getStringPoolEntry(String); + MCSymbol *Symb = DU->getStringPool().getSymbol(*Asm, String); DIEValue *Value; if (Asm->MAI->doesDwarfUseRelocationsAcrossSections()) Value = new (DIEValueAllocator) DIELabel(Symb); else { - MCSymbol *StringPool = DU->getStringPoolSym(); + MCSymbol *StringPool = DU->getStringPool().getSectionSymbol(); Value = new (DIEValueAllocator) DIEDelta(Symb, StringPool); } DIEValue *Str = new (DIEValueAllocator) DIEString(Value, String); - Die->addValue(Attribute, dwarf::DW_FORM_strp, Str); + Die.addValue(Attribute, dwarf::DW_FORM_strp, Str); } /// addExpr - Add a Dwarf expression attribute data and value. /// -void DwarfUnit::addExpr(DIELoc *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); + Die.addValue((dwarf::Attribute)0, Form, Value); } /// addLocationList - Add a Dwarf loclistptr attribute data and value. /// -void DwarfUnit::addLocationList(DIE *Die, dwarf::Attribute Attribute, +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); + Die.addValue(Attribute, Form, Value); } /// addLabel - Add a Dwarf label attribute data and value. /// -void DwarfUnit::addLabel(DIE *Die, dwarf::Attribute Attribute, dwarf::Form Form, +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); + Die.addValue(Attribute, Form, Value); } -void DwarfUnit::addLabel(DIELoc *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, +void DwarfUnit::addSectionLabel(DIE &Die, dwarf::Attribute Attribute, const MCSymbol *Label) { if (DD->getDwarfVersion() >= 4) addLabel(Die, Attribute, dwarf::DW_FORM_sec_offset, Label); @@ -270,7 +273,7 @@ void DwarfUnit::addSectionLabel(DIE *Die, dwarf::Attribute Attribute, /// addSectionOffset - Add an offset into a section attribute data and value. /// -void DwarfUnit::addSectionOffset(DIE *Die, dwarf::Attribute Attribute, +void DwarfUnit::addSectionOffset(DIE &Die, dwarf::Attribute Attribute, uint64_t Integer) { if (DD->getDwarfVersion() >= 4) addUInt(Die, Attribute, dwarf::DW_FORM_sec_offset, Integer); @@ -281,7 +284,7 @@ void DwarfUnit::addSectionOffset(DIE *Die, dwarf::Attribute Attribute, /// addLabelAddress - Add a dwarf label attribute data and value using /// DW_FORM_addr or DW_FORM_GNU_addr_index. /// -void DwarfCompileUnit::addLabelAddress(DIE *Die, dwarf::Attribute Attribute, +void DwarfCompileUnit::addLabelAddress(DIE &Die, dwarf::Attribute Attribute, const MCSymbol *Label) { if (!DD->useSplitDwarf()) @@ -290,24 +293,20 @@ void DwarfCompileUnit::addLabelAddress(DIE *Die, dwarf::Attribute Attribute, if (Label) DD->addArangeLabel(SymbolCU(this, Label)); - unsigned idx = DU->getAddrPoolIndex(Label); + unsigned idx = DD->getAddressPool().getIndex(Label); DIEValue *Value = new (DIEValueAllocator) DIEInteger(idx); - Die->addValue(Attribute, dwarf::DW_FORM_GNU_addr_index, Value); + Die.addValue(Attribute, dwarf::DW_FORM_GNU_addr_index, Value); } -void DwarfCompileUnit::addLocalLabelAddress(DIE *Die, +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 { - DIEValue *Value = new (DIEValueAllocator) DIEInteger(0); - Die->addValue(Attribute, dwarf::DW_FORM_addr, Value); - } + Die.addValue(Attribute, dwarf::DW_FORM_addr, + Label ? (DIEValue *)new (DIEValueAllocator) DIELabel(Label) + : new (DIEValueAllocator) DIEInteger(0)); } unsigned DwarfCompileUnit::getOrCreateSourceID(StringRef FileName, StringRef DirName) { @@ -329,86 +328,94 @@ unsigned DwarfTypeUnit::getOrCreateSourceID(StringRef FileName, StringRef DirNam /// 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 DwarfUnit::addOpAddress(DIELoc *Die, const MCSymbol *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); } else { addUInt(Die, dwarf::DW_FORM_data1, dwarf::DW_OP_GNU_addr_index); - addUInt(Die, dwarf::DW_FORM_GNU_addr_index, DU->getAddrPoolIndex(Sym)); + addUInt(Die, dwarf::DW_FORM_GNU_addr_index, + DD->getAddressPool().getIndex(Sym)); } } /// addSectionDelta - Add a section label delta attribute data and value. /// -void DwarfUnit::addSectionDelta(DIE *Die, dwarf::Attribute Attribute, +void DwarfUnit::addSectionDelta(DIE &Die, dwarf::Attribute Attribute, const MCSymbol *Hi, const MCSymbol *Lo) { DIEValue *Value = new (DIEValueAllocator) DIEDelta(Hi, Lo); - if (DD->getDwarfVersion() >= 4) - Die->addValue(Attribute, dwarf::DW_FORM_sec_offset, Value); - else - Die->addValue(Attribute, dwarf::DW_FORM_data4, Value); + Die.addValue(Attribute, DD->getDwarfVersion() >= 4 ? dwarf::DW_FORM_sec_offset + : dwarf::DW_FORM_data4, + Value); } -void DwarfUnit::addLabelDelta(DIE *Die, dwarf::Attribute Attribute, +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); + Die.addValue(Attribute, dwarf::DW_FORM_data4, Value); } /// addDIEEntry - Add a DIE attribute data and value. /// -void DwarfUnit::addDIEEntry(DIE *Die, dwarf::Attribute Attribute, DIE *Entry) { +void DwarfUnit::addDIEEntry(DIE &Die, dwarf::Attribute Attribute, DIE &Entry) { addDIEEntry(Die, Attribute, createDIEEntry(Entry)); } -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::addDIETypeSignature(DIE &Die, const DwarfTypeUnit &Type) { + // 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. + addFlag(Die, dwarf::DW_AT_declaration); + + Die.addValue(dwarf::DW_AT_signature, dwarf::DW_FORM_ref_sig8, + new (DIEValueAllocator) DIETypeSignature(Type)); } -void DwarfUnit::addDIEEntry(DIE *Die, dwarf::Attribute Attribute, +void DwarfUnit::addDIEEntry(DIE &Die, dwarf::Attribute Attribute, DIEEntry *Entry) { - const DIE *DieCU = Die->getUnitOrNull(); - const DIE *EntryCU = Entry->getEntry()->getUnitOrNull(); + 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 = getUnitDie(); + DieCU = &getUnitDie(); if (!EntryCU) - EntryCU = getUnitDie(); - Die->addValue(Attribute, EntryCU == DieCU ? dwarf::DW_FORM_ref4 - : dwarf::DW_FORM_ref_addr, - Entry); + EntryCU = &getUnitDie(); + Die.addValue(Attribute, + EntryCU == DieCU ? dwarf::DW_FORM_ref4 : dwarf::DW_FORM_ref_addr, + Entry); } /// Create a DIE with the given Tag, add the DIE to its parent, and /// call insertDIE if MD is not null. -DIE *DwarfUnit::createAndAddDIE(unsigned Tag, DIE &Parent, DIDescriptor N) { - DIE *Die = new DIE(Tag); - Parent.addChild(Die); +DIE &DwarfUnit::createAndAddDIE(unsigned Tag, DIE &Parent, DIDescriptor N) { + assert(Tag != dwarf::DW_TAG_auto_variable && + Tag != dwarf::DW_TAG_arg_variable); + Parent.addChild(make_unique<DIE>((dwarf::Tag)Tag)); + DIE &Die = *Parent.getChildren().back(); if (N) - insertDIE(N, Die); + insertDIE(N, &Die); return Die; } /// addBlock - Add block data. /// -void DwarfUnit::addBlock(DIE *Die, dwarf::Attribute Attribute, DIELoc *Loc) { +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); + Die.addValue(Attribute, Loc->BestForm(DD->getDwarfVersion()), Loc); } -void DwarfUnit::addBlock(DIE *Die, dwarf::Attribute Attribute, +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); + Die.addValue(Attribute, Block->BestForm(), Block); } /// addSourceLine - Add location information to specified debug information /// entry. -void DwarfUnit::addSourceLine(DIE *Die, unsigned Line, StringRef File, +void DwarfUnit::addSourceLine(DIE &Die, unsigned Line, StringRef File, StringRef Directory) { if (Line == 0) return; @@ -421,7 +428,7 @@ void DwarfUnit::addSourceLine(DIE *Die, unsigned Line, StringRef File, /// addSourceLine - Add location information to specified debug information /// entry. -void DwarfUnit::addSourceLine(DIE *Die, DIVariable V) { +void DwarfUnit::addSourceLine(DIE &Die, DIVariable V) { assert(V.isVariable()); addSourceLine(Die, V.getLineNumber(), V.getContext().getFilename(), @@ -430,7 +437,7 @@ void DwarfUnit::addSourceLine(DIE *Die, DIVariable V) { /// addSourceLine - Add location information to specified debug information /// entry. -void DwarfUnit::addSourceLine(DIE *Die, DIGlobalVariable G) { +void DwarfUnit::addSourceLine(DIE &Die, DIGlobalVariable G) { assert(G.isGlobalVariable()); addSourceLine(Die, G.getLineNumber(), G.getFilename(), G.getDirectory()); @@ -438,7 +445,7 @@ void DwarfUnit::addSourceLine(DIE *Die, DIGlobalVariable G) { /// addSourceLine - Add location information to specified debug information /// entry. -void DwarfUnit::addSourceLine(DIE *Die, DISubprogram SP) { +void DwarfUnit::addSourceLine(DIE &Die, DISubprogram SP) { assert(SP.isSubprogram()); addSourceLine(Die, SP.getLineNumber(), SP.getFilename(), SP.getDirectory()); @@ -446,7 +453,7 @@ void DwarfUnit::addSourceLine(DIE *Die, DISubprogram SP) { /// addSourceLine - Add location information to specified debug information /// entry. -void DwarfUnit::addSourceLine(DIE *Die, DIType Ty) { +void DwarfUnit::addSourceLine(DIE &Die, DIType Ty) { assert(Ty.isType()); addSourceLine(Die, Ty.getLineNumber(), Ty.getFilename(), Ty.getDirectory()); @@ -454,7 +461,7 @@ void DwarfUnit::addSourceLine(DIE *Die, DIType Ty) { /// addSourceLine - Add location information to specified debug information /// entry. -void DwarfUnit::addSourceLine(DIE *Die, DIObjCProperty Ty) { +void DwarfUnit::addSourceLine(DIE &Die, DIObjCProperty Ty) { assert(Ty.isObjCProperty()); DIFile File = Ty.getFile(); @@ -464,7 +471,7 @@ void DwarfUnit::addSourceLine(DIE *Die, DIObjCProperty Ty) { /// addSourceLine - Add location information to specified debug information /// entry. -void DwarfUnit::addSourceLine(DIE *Die, DINameSpace NS) { +void DwarfUnit::addSourceLine(DIE &Die, DINameSpace NS) { assert(NS.Verify()); addSourceLine(Die, NS.getLineNumber(), NS.getFilename(), NS.getDirectory()); @@ -472,7 +479,7 @@ void DwarfUnit::addSourceLine(DIE *Die, DINameSpace NS) { /// addVariableAddress - Add DW_AT_location attribute for a /// DbgVariable based on provided MachineLocation. -void DwarfUnit::addVariableAddress(const DbgVariable &DV, DIE *Die, +void DwarfUnit::addVariableAddress(const DbgVariable &DV, DIE &Die, MachineLocation Location) { if (DV.variableHasComplexAddress()) addComplexAddress(DV, Die, dwarf::DW_AT_location, Location); @@ -484,7 +491,7 @@ void DwarfUnit::addVariableAddress(const DbgVariable &DV, DIE *Die, } /// addRegisterOp - Add register operand. -void DwarfUnit::addRegisterOp(DIELoc *TheDie, unsigned Reg) { +void DwarfUnit::addRegisterOp(DIELoc &TheDie, unsigned Reg) { const TargetRegisterInfo *RI = Asm->TM.getRegisterInfo(); int DWReg = RI->getDwarfRegNum(Reg, false); bool isSubRegister = DWReg < 0; @@ -529,7 +536,7 @@ void DwarfUnit::addRegisterOp(DIELoc *TheDie, unsigned Reg) { } /// addRegisterOffset - Add register offset. -void DwarfUnit::addRegisterOffset(DIELoc *TheDie, unsigned Reg, +void DwarfUnit::addRegisterOffset(DIELoc &TheDie, unsigned Reg, int64_t Offset) { const TargetRegisterInfo *RI = Asm->TM.getRegisterInfo(); unsigned DWReg = RI->getDwarfRegNum(Reg, false); @@ -548,16 +555,16 @@ void DwarfUnit::addRegisterOffset(DIELoc *TheDie, unsigned Reg, /// addAddress - Add an address attribute to a die based on the location /// provided. -void DwarfUnit::addAddress(DIE *Die, dwarf::Attribute Attribute, +void DwarfUnit::addAddress(DIE &Die, dwarf::Attribute Attribute, const MachineLocation &Location, bool Indirect) { DIELoc *Loc = new (DIEValueAllocator) DIELoc(); if (Location.isReg() && !Indirect) - addRegisterOp(Loc, Location.getReg()); + addRegisterOp(*Loc, Location.getReg()); else { - addRegisterOffset(Loc, Location.getReg(), Location.getOffset()); + addRegisterOffset(*Loc, Location.getReg(), Location.getOffset()); if (Indirect && !Location.isReg()) { - addUInt(Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_deref); + addUInt(*Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_deref); } } @@ -570,7 +577,7 @@ void DwarfUnit::addAddress(DIE *Die, dwarf::Attribute Attribute, /// given the extra address information encoded in the DbgVariable, starting /// from the starting location. Add the DWARF information to the die. /// -void DwarfUnit::addComplexAddress(const DbgVariable &DV, DIE *Die, +void DwarfUnit::addComplexAddress(const DbgVariable &DV, DIE &Die, dwarf::Attribute Attribute, const MachineLocation &Location) { DIELoc *Loc = new (DIEValueAllocator) DIELoc(); @@ -580,21 +587,21 @@ void DwarfUnit::addComplexAddress(const DbgVariable &DV, DIE *Die, 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(Loc, Location.getReg(), DV.getAddrElement(1)); + addRegisterOffset(*Loc, Location.getReg(), DV.getAddrElement(1)); i = 2; } else - addRegisterOp(Loc, Location.getReg()); + addRegisterOp(*Loc, Location.getReg()); } else - addRegisterOffset(Loc, 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(Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_plus_uconst); - addUInt(Loc, 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(Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_deref); + addUInt(*Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_deref); } else llvm_unreachable("unknown DIBuilder Opcode"); } @@ -663,7 +670,7 @@ void DwarfUnit::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 DwarfUnit::addBlockByrefAddress(const DbgVariable &DV, DIE *Die, +void DwarfUnit::addBlockByrefAddress(const DbgVariable &DV, DIE &Die, dwarf::Attribute Attribute, const MachineLocation &Location) { DIType Ty = DV.getType(); @@ -705,68 +712,78 @@ void DwarfUnit::addBlockByrefAddress(const DbgVariable &DV, DIE *Die, DIELoc *Loc = new (DIEValueAllocator) DIELoc(); if (Location.isReg()) - addRegisterOp(Loc, Location.getReg()); + addRegisterOp(*Loc, Location.getReg()); else - addRegisterOffset(Loc, 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(Loc, 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(Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_plus_uconst); - addUInt(Loc, 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(Loc, 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(Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_plus_uconst); - addUInt(Loc, 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, Loc); } -/// isTypeSigned - Return true if the type is signed. -static bool isTypeSigned(DwarfDebug *DD, DIType Ty, int *SizeInBits) { - if (Ty.isDerivedType()) - return isTypeSigned(DD, DD->resolve(DIDerivedType(Ty).getTypeDerivedFrom()), - SizeInBits); - if (Ty.isBasicType()) - if (DIBasicType(Ty).getEncoding() == dwarf::DW_ATE_signed || - DIBasicType(Ty).getEncoding() == dwarf::DW_ATE_signed_char) { - *SizeInBits = Ty.getSizeInBits(); - return true; - } - return false; -} - /// Return true if type encoding is unsigned. static bool isUnsignedDIType(DwarfDebug *DD, DIType Ty) { DIDerivedType DTy(Ty); - if (DTy.isDerivedType()) - return isUnsignedDIType(DD, DD->resolve(DTy.getTypeDerivedFrom())); - - DIBasicType BTy(Ty); - if (BTy.isBasicType()) { - unsigned Encoding = BTy.getEncoding(); - if (Encoding == dwarf::DW_ATE_unsigned || - Encoding == dwarf::DW_ATE_unsigned_char || - Encoding == dwarf::DW_ATE_boolean) + if (DTy.isDerivedType()) { + dwarf::Tag T = (dwarf::Tag)Ty.getTag(); + // Encode pointer constants as unsigned bytes. This is used at least for + // null pointer constant emission. + // FIXME: reference and rvalue_reference /probably/ shouldn't be allowed + // here, but accept them for now due to a bug in SROA producing bogus + // dbg.values. + if (T == dwarf::DW_TAG_pointer_type || + T == dwarf::DW_TAG_ptr_to_member_type || + T == dwarf::DW_TAG_reference_type || + T == dwarf::DW_TAG_rvalue_reference_type) return true; + assert(T == dwarf::DW_TAG_typedef || T == dwarf::DW_TAG_const_type || + T == dwarf::DW_TAG_volatile_type || + T == dwarf::DW_TAG_restrict_type || + T == dwarf::DW_TAG_enumeration_type); + if (DITypeRef Deriv = DTy.getTypeDerivedFrom()) + return isUnsignedDIType(DD, DD->resolve(Deriv)); + // FIXME: Enums without a fixed underlying type have unknown signedness + // here, leading to incorrectly emitted constants. + assert(DTy.getTag() == dwarf::DW_TAG_enumeration_type); + return false; } - return false; + + DIBasicType BTy(Ty); + assert(BTy.isBasicType()); + unsigned Encoding = BTy.getEncoding(); + assert((Encoding == dwarf::DW_ATE_unsigned || + Encoding == dwarf::DW_ATE_unsigned_char || + Encoding == dwarf::DW_ATE_signed || + Encoding == dwarf::DW_ATE_signed_char || + Encoding == dwarf::DW_ATE_UTF || Encoding == dwarf::DW_ATE_boolean) && + "Unsupported encoding"); + return (Encoding == dwarf::DW_ATE_unsigned || + Encoding == dwarf::DW_ATE_unsigned_char || + Encoding == dwarf::DW_ATE_UTF || Encoding == dwarf::DW_ATE_boolean); } /// If this type is derived from a base type then return base type size. @@ -798,47 +815,8 @@ static uint64_t getBaseTypeSize(DwarfDebug *DD, DIDerivedType Ty) { return BaseType.getSizeInBits(); } -/// addConstantValue - Add constant value entry in variable DIE. -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) - assert(MO.isImm() && "Invalid machine operand!"); - int SizeInBits = -1; - bool SignedConstant = isTypeSigned(DD, Ty, &SizeInBits); - dwarf::Form Form; - - // If we're a signed constant definitely use sdata. - if (SignedConstant) { - addSInt(Die, dwarf::DW_AT_const_value, dwarf::DW_FORM_sdata, MO.getImm()); - return; - } - - // Else use data for now unless it's larger than we can deal with. - switch (SizeInBits) { - case 8: - Form = dwarf::DW_FORM_data1; - break; - case 16: - Form = dwarf::DW_FORM_data2; - break; - case 32: - Form = dwarf::DW_FORM_data4; - break; - case 64: - Form = dwarf::DW_FORM_data8; - break; - default: - Form = dwarf::DW_FORM_udata; - addUInt(Die, dwarf::DW_AT_const_value, Form, MO.getImm()); - return; - } - addUInt(Die, dwarf::DW_AT_const_value, Form, MO.getImm()); -} - /// addConstantFPValue - Add constant value entry in variable DIE. -void DwarfUnit::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(); @@ -855,55 +833,47 @@ void DwarfUnit::addConstantFPValue(DIE *Die, const MachineOperand &MO) { // Output the constant to DWARF one byte at a time. for (; Start != Stop; Start += Incr) - addUInt(Block, dwarf::DW_FORM_data1, (unsigned char)0xFF & FltPtr[Start]); + addUInt(*Block, dwarf::DW_FORM_data1, (unsigned char)0xFF & FltPtr[Start]); addBlock(Die, dwarf::DW_AT_const_value, Block); } /// addConstantFPValue - Add constant value entry in variable DIE. -void DwarfUnit::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 DwarfUnit::addConstantValue(DIE *Die, const ConstantInt *CI, - bool Unsigned) { - addConstantValue(Die, CI->getValue(), Unsigned); +void DwarfUnit::addConstantValue(DIE &Die, const ConstantInt *CI, DIType Ty) { + addConstantValue(Die, CI->getValue(), Ty); +} + +/// addConstantValue - Add constant value entry in variable DIE. +void DwarfUnit::addConstantValue(DIE &Die, const MachineOperand &MO, + DIType Ty) { + assert(MO.isImm() && "Invalid machine operand!"); + + addConstantValue(Die, isUnsignedDIType(DD, Ty), MO.getImm()); +} + +void DwarfUnit::addConstantValue(DIE &Die, bool Unsigned, uint64_t Val) { + // FIXME: This is a bit conservative/simple - it emits negative values always + // sign extended to 64 bits rather than minimizing the number of bytes. + addUInt(Die, dwarf::DW_AT_const_value, + Unsigned ? dwarf::DW_FORM_udata : dwarf::DW_FORM_sdata, Val); +} + +void DwarfUnit::addConstantValue(DIE &Die, const APInt &Val, DIType Ty) { + addConstantValue(Die, Val, isUnsignedDIType(DD, Ty)); } // addConstantValue - Add constant value entry in variable DIE. -void DwarfUnit::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. - if (!Unsigned) { - addSInt(Die, dwarf::DW_AT_const_value, dwarf::DW_FORM_sdata, - Val.getSExtValue()); - return; - } - - // Else use data for now unless it's larger than we can deal with. - dwarf::Form Form; - switch (CIBitWidth) { - case 8: - Form = dwarf::DW_FORM_data1; - break; - case 16: - Form = dwarf::DW_FORM_data2; - break; - case 32: - Form = dwarf::DW_FORM_data4; - break; - case 64: - Form = dwarf::DW_FORM_data8; - break; - default: - addUInt(Die, dwarf::DW_AT_const_value, dwarf::DW_FORM_udata, - Val.getZExtValue()); - return; - } - addUInt(Die, dwarf::DW_AT_const_value, Form, Val.getZExtValue()); + addConstantValue(Die, Unsigned, + Unsigned ? Val.getZExtValue() : Val.getSExtValue()); return; } @@ -922,7 +892,7 @@ void DwarfUnit::addConstantValue(DIE *Die, const APInt &Val, bool Unsigned) { c = Ptr64[i / 8] >> (8 * (i & 7)); else c = Ptr64[(NumBytes - 1 - i) / 8] >> (8 * ((NumBytes - 1 - i) & 7)); - addUInt(Block, dwarf::DW_FORM_data1, c); + addUInt(*Block, dwarf::DW_FORM_data1, c); } addBlock(Die, dwarf::DW_AT_const_value, Block); @@ -945,7 +915,7 @@ void DwarfUnit::addTemplateParams(DIE &Buffer, DIArray TParams) { /// getOrCreateContextDIE - Get context owner's DIE. DIE *DwarfUnit::getOrCreateContextDIE(DIScope Context) { if (!Context || Context.isFile()) - return getUnitDie(); + return &getUnitDie(); if (Context.isType()) return getOrCreateTypeDIE(DIType(Context)); if (Context.isNameSpace()) @@ -959,66 +929,68 @@ DIE *DwarfUnit::createTypeDIE(DICompositeType Ty) { DIScope Context = resolve(Ty.getContext()); DIE *ContextDIE = getOrCreateContextDIE(Context); - DIE *TyDIE = getDIE(Ty); - if (TyDIE) + if (DIE *TyDIE = getDIE(Ty)) return TyDIE; // Create new type. - TyDIE = createAndAddDIE(Ty.getTag(), *ContextDIE, Ty); + DIE &TyDIE = createAndAddDIE(Ty.getTag(), *ContextDIE, Ty); - constructTypeDIE(*TyDIE, Ty); + constructTypeDIE(TyDIE, Ty); updateAcceleratorTables(Context, Ty, TyDIE); - return TyDIE; + return &TyDIE; } /// getOrCreateTypeDIE - Find existing DIE or create new DIE for the /// given DIType. DIE *DwarfUnit::getOrCreateTypeDIE(const MDNode *TyNode) { if (!TyNode) - return NULL; + return nullptr; DIType Ty(TyNode); assert(Ty.isType()); assert(Ty == resolve(Ty.getRef()) && "type was not uniqued, possible ODR violation."); + // DW_TAG_restrict_type is not supported in DWARF2 + if (Ty.getTag() == dwarf::DW_TAG_restrict_type && DD->getDwarfVersion() <= 2) + return getOrCreateTypeDIE(resolve(DIDerivedType(Ty).getTypeDerivedFrom())); + // Construct the context before querying for the existence of the DIE in case // such construction creates the DIE. DIScope Context = resolve(Ty.getContext()); DIE *ContextDIE = getOrCreateContextDIE(Context); assert(ContextDIE); - DIE *TyDIE = getDIE(Ty); - if (TyDIE) + if (DIE *TyDIE = getDIE(Ty)) return TyDIE; // Create new type. - TyDIE = createAndAddDIE(Ty.getTag(), *ContextDIE, Ty); + DIE &TyDIE = createAndAddDIE(Ty.getTag(), *ContextDIE, Ty); updateAcceleratorTables(Context, Ty, TyDIE); if (Ty.isBasicType()) - constructTypeDIE(*TyDIE, DIBasicType(Ty)); + constructTypeDIE(TyDIE, DIBasicType(Ty)); 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; + return &TyDIE; } - constructTypeDIE(*TyDIE, CTy); + constructTypeDIE(TyDIE, CTy); } else { assert(Ty.isDerivedType() && "Unknown kind of DIType"); - constructTypeDIE(*TyDIE, DIDerivedType(Ty)); + constructTypeDIE(TyDIE, DIDerivedType(Ty)); } - return TyDIE; + return &TyDIE; } void DwarfUnit::updateAcceleratorTables(DIScope Context, DIType Ty, - const DIE *TyDIE) { + const DIE &TyDIE) { if (!Ty.getName().empty() && !Ty.isForwardDecl()) { bool IsImplementation = 0; if (Ty.isCompositeType()) { @@ -1028,17 +1000,18 @@ void DwarfUnit::updateAcceleratorTables(DIScope Context, DIType Ty, IsImplementation = (CT.getRunTimeLang() == 0) || CT.isObjcClassComplete(); } unsigned Flags = IsImplementation ? dwarf::DW_FLAG_type_implementation : 0; - addAccelType(Ty.getName(), std::make_pair(TyDIE, Flags)); + DD->addAccelType(Ty.getName(), TyDIE, Flags); if ((!Context || Context.isCompileUnit() || Context.isFile() || Context.isNameSpace()) && getCUNode().getEmissionKind() != DIBuilder::LineTablesOnly) - GlobalTypes[getParentContextString(Context) + Ty.getName().str()] = TyDIE; + GlobalTypes[getParentContextString(Context) + Ty.getName().str()] = + &TyDIE; } } /// addType - Add a new type attribute to the specified entity. -void DwarfUnit::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. @@ -1053,54 +1026,17 @@ void DwarfUnit::addType(DIE *Entity, DIType Ty, dwarf::Attribute Attribute) { DIE *Buffer = getOrCreateTypeDIE(Ty); // Set up proxy. - Entry = createDIEEntry(Buffer); + Entry = createDIEEntry(*Buffer); insertDIEEntry(Ty, Entry); addDIEEntry(Entity, Attribute, Entry); } -// 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 DwarfUnit::addAccelName(StringRef Name, const DIE *Die) { - if (!DD->useDwarfAccelTables()) - return; - DU->getStringPoolEntry(Name); - std::vector<const DIE *> &DIEs = AccelNames[Name]; - DIEs.push_back(Die); -} - -void DwarfUnit::addAccelObjC(StringRef Name, const DIE *Die) { - if (!DD->useDwarfAccelTables()) - return; - DU->getStringPoolEntry(Name); - std::vector<const DIE *> &DIEs = AccelObjC[Name]; - DIEs.push_back(Die); -} - -void DwarfUnit::addAccelNamespace(StringRef Name, const DIE *Die) { - if (!DD->useDwarfAccelTables()) - return; - DU->getStringPoolEntry(Name); - std::vector<const DIE *> &DIEs = AccelNamespace[Name]; - DIEs.push_back(Die); -} - -void DwarfUnit::addAccelType(StringRef Name, - std::pair<const DIE *, unsigned> Die) { - if (!DD->useDwarfAccelTables()) - return; - DU->getStringPoolEntry(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 DwarfUnit::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; + GlobalNames[FullName] = &Die; } /// getParentContextString - Walks the metadata parent chain in a language @@ -1149,17 +1085,17 @@ void DwarfUnit::constructTypeDIE(DIE &Buffer, DIBasicType BTy) { StringRef Name = BTy.getName(); // Add name if not anonymous or intermediate type. if (!Name.empty()) - addString(&Buffer, dwarf::DW_AT_name, Name); + addString(Buffer, dwarf::DW_AT_name, Name); // An unspecified type only has a name attribute. if (BTy.getTag() == dwarf::DW_TAG_unspecified_type) return; - addUInt(&Buffer, dwarf::DW_AT_encoding, dwarf::DW_FORM_data1, + addUInt(Buffer, dwarf::DW_AT_encoding, dwarf::DW_FORM_data1, BTy.getEncoding()); uint64_t Size = BTy.getSizeInBits() >> 3; - addUInt(&Buffer, dwarf::DW_AT_byte_size, None, Size); + addUInt(Buffer, dwarf::DW_AT_byte_size, None, Size); } /// constructTypeDIE - Construct derived type die from DIDerivedType. @@ -1172,22 +1108,22 @@ void DwarfUnit::constructTypeDIE(DIE &Buffer, DIDerivedType DTy) { // Map to main type, void will not have a type. DIType FromTy = resolve(DTy.getTypeDerivedFrom()); if (FromTy) - addType(&Buffer, FromTy); + addType(Buffer, FromTy); // Add name if not anonymous or intermediate type. if (!Name.empty()) - addString(&Buffer, dwarf::DW_AT_name, Name); + addString(Buffer, dwarf::DW_AT_name, Name); // Add size if non-zero (derived types might be zero-sized.) if (Size && Tag != dwarf::DW_TAG_pointer_type) - addUInt(&Buffer, dwarf::DW_AT_byte_size, None, Size); + addUInt(Buffer, dwarf::DW_AT_byte_size, None, Size); if (Tag == dwarf::DW_TAG_ptr_to_member_type) - addDIEEntry(&Buffer, dwarf::DW_AT_containing_type, - getOrCreateTypeDIE(resolve(DTy.getClassType()))); + addDIEEntry(Buffer, dwarf::DW_AT_containing_type, + *getOrCreateTypeDIE(resolve(DTy.getClassType()))); // Add source line info if available and TyDesc is not a forward declaration. if (!DTy.isForwardDecl()) - addSourceLine(&Buffer, DTy); + addSourceLine(Buffer, DTy); } /// constructSubprogramArguments - Construct function argument DIEs. @@ -1198,7 +1134,7 @@ void DwarfUnit::constructSubprogramArguments(DIE &Buffer, DIArray Args) { 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); + DIE &Arg = createAndAddDIE(dwarf::DW_TAG_formal_parameter, Buffer); addType(Arg, DIType(Ty)); if (DIType(Ty).isArtificial()) addFlag(Arg, dwarf::DW_AT_artificial); @@ -1226,7 +1162,7 @@ void DwarfUnit::constructTypeDIE(DIE &Buffer, DICompositeType CTy) { DIArray Elements = CTy.getTypeArray(); DIType RTy(Elements.getElement(0)); if (RTy) - addType(&Buffer, RTy); + addType(Buffer, RTy); bool isPrototyped = true; if (Elements.getNumElements() == 2 && @@ -1241,13 +1177,13 @@ void DwarfUnit::constructTypeDIE(DIE &Buffer, DICompositeType CTy) { if (isPrototyped && (Language == dwarf::DW_LANG_C89 || Language == dwarf::DW_LANG_C99 || Language == dwarf::DW_LANG_ObjC)) - addFlag(&Buffer, dwarf::DW_AT_prototyped); + addFlag(Buffer, dwarf::DW_AT_prototyped); if (CTy.isLValueReference()) - addFlag(&Buffer, dwarf::DW_AT_reference); + addFlag(Buffer, dwarf::DW_AT_reference); if (CTy.isRValueReference()) - addFlag(&Buffer, dwarf::DW_AT_rvalue_reference); + addFlag(Buffer, dwarf::DW_AT_rvalue_reference); } break; case dwarf::DW_TAG_structure_type: case dwarf::DW_TAG_union_type: @@ -1256,13 +1192,12 @@ void DwarfUnit::constructTypeDIE(DIE &Buffer, DICompositeType CTy) { DIArray Elements = CTy.getTypeArray(); for (unsigned i = 0, N = Elements.getNumElements(); i < N; ++i) { DIDescriptor Element = Elements.getElement(i); - DIE *ElemDie = NULL; if (Element.isSubprogram()) - ElemDie = getOrCreateSubprogramDIE(DISubprogram(Element)); + getOrCreateSubprogramDIE(DISubprogram(Element)); else if (Element.isDerivedType()) { DIDerivedType DDTy(Element); if (DDTy.getTag() == dwarf::DW_TAG_friend) { - ElemDie = createAndAddDIE(dwarf::DW_TAG_friend, Buffer); + DIE &ElemDie = createAndAddDIE(dwarf::DW_TAG_friend, Buffer); addType(ElemDie, resolve(DDTy.getTypeDerivedFrom()), dwarf::DW_AT_friend); } else if (DDTy.isStaticMember()) { @@ -1272,7 +1207,7 @@ void DwarfUnit::constructTypeDIE(DIE &Buffer, DICompositeType CTy) { } } else if (Element.isObjCProperty()) { DIObjCProperty Property(Element); - ElemDie = createAndAddDIE(Property.getTag(), Buffer); + DIE &ElemDie = createAndAddDIE(Property.getTag(), Buffer); StringRef PropertyName = Property.getObjCPropertyName(); addString(ElemDie, dwarf::DW_AT_APPLE_property_name, PropertyName); if (Property.getType()) @@ -1311,15 +1246,15 @@ void DwarfUnit::constructTypeDIE(DIE &Buffer, DICompositeType CTy) { } if (CTy.isAppleBlockExtension()) - addFlag(&Buffer, dwarf::DW_AT_APPLE_block); + addFlag(Buffer, dwarf::DW_AT_APPLE_block); DICompositeType ContainingType(resolve(CTy.getContainingType())); if (ContainingType) - addDIEEntry(&Buffer, dwarf::DW_AT_containing_type, - getOrCreateTypeDIE(ContainingType)); + addDIEEntry(Buffer, dwarf::DW_AT_containing_type, + *getOrCreateTypeDIE(ContainingType)); if (CTy.isObjcClassComplete()) - addFlag(&Buffer, dwarf::DW_AT_APPLE_objc_complete_type); + addFlag(Buffer, dwarf::DW_AT_APPLE_objc_complete_type); // Add template parameters to a class, structure or union types. // FIXME: The support isn't in the metadata for this yet. @@ -1335,7 +1270,7 @@ void DwarfUnit::constructTypeDIE(DIE &Buffer, DICompositeType CTy) { // Add name if not anonymous or intermediate type. if (!Name.empty()) - addString(&Buffer, dwarf::DW_AT_name, Name); + addString(Buffer, dwarf::DW_AT_name, Name); if (Tag == dwarf::DW_TAG_enumeration_type || Tag == dwarf::DW_TAG_class_type || Tag == dwarf::DW_TAG_structure_type || @@ -1343,23 +1278,23 @@ void DwarfUnit::constructTypeDIE(DIE &Buffer, DICompositeType CTy) { // Add size if non-zero (derived types might be zero-sized.) // TODO: Do we care about size for enum forward declarations? if (Size) - addUInt(&Buffer, dwarf::DW_AT_byte_size, None, Size); + addUInt(Buffer, dwarf::DW_AT_byte_size, None, Size); else if (!CTy.isForwardDecl()) // Add zero size if it is not a forward declaration. - addUInt(&Buffer, dwarf::DW_AT_byte_size, None, 0); + addUInt(Buffer, dwarf::DW_AT_byte_size, None, 0); // If we're a forward decl, say so. if (CTy.isForwardDecl()) - addFlag(&Buffer, dwarf::DW_AT_declaration); + addFlag(Buffer, dwarf::DW_AT_declaration); // Add source line info if available. if (!CTy.isForwardDecl()) - addSourceLine(&Buffer, CTy); + addSourceLine(Buffer, CTy); // No harm in adding the runtime language to the declaration. unsigned RLang = CTy.getRunTimeLang(); if (RLang) - addUInt(&Buffer, dwarf::DW_AT_APPLE_runtime_class, dwarf::DW_FORM_data1, + addUInt(Buffer, dwarf::DW_AT_APPLE_runtime_class, dwarf::DW_FORM_data1, RLang); } } @@ -1368,7 +1303,7 @@ void DwarfUnit::constructTypeDIE(DIE &Buffer, DICompositeType CTy) { /// DITemplateTypeParameter. void DwarfUnit::constructTemplateTypeParameterDIE(DIE &Buffer, DITemplateTypeParameter TP) { - DIE *ParamDIE = + DIE &ParamDIE = createAndAddDIE(dwarf::DW_TAG_template_type_parameter, Buffer); // Add the type if it exists, it could be void and therefore no type. if (TP.getType()) @@ -1382,7 +1317,7 @@ void DwarfUnit::constructTemplateTypeParameterDIE(DIE &Buffer, void DwarfUnit::constructTemplateValueParameterDIE(DIE &Buffer, DITemplateValueParameter VP) { - DIE *ParamDIE = createAndAddDIE(VP.getTag(), Buffer); + DIE &ParamDIE = createAndAddDIE(VP.getTag(), Buffer); // Add the type if there is one, template template and template parameter // packs will not have a type. @@ -1392,16 +1327,15 @@ DwarfUnit::constructTemplateValueParameterDIE(DIE &Buffer, addString(ParamDIE, dwarf::DW_AT_name, VP.getName()); if (Value *Val = VP.getValue()) { if (ConstantInt *CI = dyn_cast<ConstantInt>(Val)) - addConstantValue(ParamDIE, CI, - isUnsignedDIType(DD, resolve(VP.getType()))); + addConstantValue(ParamDIE, CI, resolve(VP.getType())); else if (GlobalValue *GV = dyn_cast<GlobalValue>(Val)) { // For declaration non-type template parameters (such as global values and // functions) DIELoc *Loc = new (DIEValueAllocator) DIELoc(); - addOpAddress(Loc, Asm->getSymbol(GV)); + 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(Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_stack_value); + 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)); @@ -1410,7 +1344,7 @@ DwarfUnit::constructTemplateValueParameterDIE(DIE &Buffer, } else if (VP.getTag() == dwarf::DW_TAG_GNU_template_parameter_pack) { assert(isa<MDNode>(Val)); DIArray A(cast<MDNode>(Val)); - addTemplateParams(*ParamDIE, A); + addTemplateParams(ParamDIE, A); } } } @@ -1421,19 +1355,18 @@ DIE *DwarfUnit::getOrCreateNameSpace(DINameSpace NS) { // such construction creates the DIE. DIE *ContextDIE = getOrCreateContextDIE(NS.getContext()); - DIE *NDie = getDIE(NS); - if (NDie) + if (DIE *NDie = getDIE(NS)) return NDie; - NDie = createAndAddDIE(dwarf::DW_TAG_namespace, *ContextDIE, NS); + DIE &NDie = createAndAddDIE(dwarf::DW_TAG_namespace, *ContextDIE, NS); if (!NS.getName().empty()) { addString(NDie, dwarf::DW_AT_name, NS.getName()); - addAccelNamespace(NS.getName(), NDie); + DD->addAccelNamespace(NS.getName(), NDie); addGlobalName(NS.getName(), NDie, NS.getContext()); } else - addAccelNamespace("(anonymous namespace)", NDie); + DD->addAccelNamespace("(anonymous namespace)", NDie); addSourceLine(NDie, NS); - return NDie; + return &NDie; } /// getOrCreateSubprogramDIE - Create new DIE using SP. @@ -1441,47 +1374,58 @@ 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). - DIScope Context = resolve(SP.getContext()); - DIE *ContextDIE = getOrCreateContextDIE(Context); + DIE *ContextDIE = getOrCreateContextDIE(resolve(SP.getContext())); - // Unique declarations based on the ODR, where applicable. - SP = DISubprogram(DD->resolve(SP.getRef())); - assert(SP.Verify()); - - DIE *SPDie = getDIE(SP); - if (SPDie) + if (DIE *SPDie = getDIE(SP)) return SPDie; - DISubprogram SPDecl = SP.getFunctionDeclaration(); - if (SPDecl.isSubprogram()) + if (DISubprogram SPDecl = SP.getFunctionDeclaration()) { // Add subprogram definitions to the CU die directly. - ContextDIE = UnitDie.get(); + ContextDIE = &getUnitDie(); + // Build the decl now to ensure it preceeds the definition. + getOrCreateSubprogramDIE(SPDecl); + } // DW_TAG_inlined_subroutine may refer to this DIE. - SPDie = createAndAddDIE(dwarf::DW_TAG_subprogram, *ContextDIE, SP); - - DIE *DeclDie = NULL; - if (SPDecl.isSubprogram()) - DeclDie = getOrCreateSubprogramDIE(SPDecl); + DIE &SPDie = createAndAddDIE(dwarf::DW_TAG_subprogram, *ContextDIE, SP); - // Add function template parameters. - addTemplateParams(*SPDie, SP.getTemplateParams()); + // Abort here and fill this in later, depending on whether or not this + // subprogram turns out to have inlined instances or not. + if (SP.isDefinition()) + return &SPDie; - // If this DIE is going to refer declaration info using AT_specification - // then there is no need to add other attributes. - if (DeclDie) { - // Refer function declaration directly. - addDIEEntry(SPDie, dwarf::DW_AT_specification, DeclDie); + applySubprogramAttributes(SP, SPDie); + return &SPDie; +} - return SPDie; +void DwarfUnit::applySubprogramAttributes(DISubprogram SP, DIE &SPDie) { + DIE *DeclDie = nullptr; + StringRef DeclLinkageName; + if (DISubprogram SPDecl = SP.getFunctionDeclaration()) { + DeclDie = getDIE(SPDecl); + assert(DeclDie); + DeclLinkageName = SPDecl.getLinkageName(); } - // Add the linkage name if we have one. + // Add function template parameters. + addTemplateParams(SPDie, SP.getTemplateParams()); + + // Add the linkage name if we have one and it isn't in the Decl. StringRef LinkageName = SP.getLinkageName(); - if (!LinkageName.empty()) + assert(((LinkageName.empty() || DeclLinkageName.empty()) || + LinkageName == DeclLinkageName) && + "decl has a linkage name and it is different"); + if (!LinkageName.empty() && DeclLinkageName.empty()) addString(SPDie, dwarf::DW_AT_MIPS_linkage_name, GlobalValue::getRealLinkageName(LinkageName)); + if (DeclDie) { + // Refer to the function declaration where all the other attributes will be + // found. + addDIEEntry(SPDie, dwarf::DW_AT_specification, *DeclDie); + return; + } + // Constructors and operators for anonymous aggregates do not have names. if (!SP.getName().empty()) addString(SPDie, dwarf::DW_AT_name, SP.getName()); @@ -1510,11 +1454,11 @@ DIE *DwarfUnit::getOrCreateSubprogramDIE(DISubprogram SP) { if (VK) { addUInt(SPDie, dwarf::DW_AT_virtuality, dwarf::DW_FORM_data1, VK); DIELoc *Block = getDIELoc(); - addUInt(Block, dwarf::DW_FORM_data1, dwarf::DW_OP_constu); - addUInt(Block, dwarf::DW_FORM_udata, SP.getVirtualIndex()); + 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); ContainingTypeMap.insert( - std::make_pair(SPDie, resolve(SP.getContainingType()))); + std::make_pair(&SPDie, resolve(SP.getContainingType()))); } if (!SP.isDefinition()) { @@ -1522,7 +1466,7 @@ DIE *DwarfUnit::getOrCreateSubprogramDIE(DISubprogram SP) { // Add arguments. Do not add arguments for subprogram definition. They will // be handled while processing variables. - constructSubprogramArguments(*SPDie, Args); + constructSubprogramArguments(SPDie, Args); } if (SP.isArtificial()) @@ -1556,8 +1500,6 @@ DIE *DwarfUnit::getOrCreateSubprogramDIE(DISubprogram SP) { if (SP.isExplicit()) addFlag(SPDie, dwarf::DW_AT_explicit); - - return SPDie; } // Return const expression if value is a GEP to access merged global @@ -1567,22 +1509,22 @@ static const ConstantExpr *getMergedGlobalExpr(const Value *V) { const ConstantExpr *CE = dyn_cast_or_null<ConstantExpr>(V); if (!CE || CE->getNumOperands() != 3 || CE->getOpcode() != Instruction::GetElementPtr) - return NULL; + return nullptr; // First operand points to a global struct. Value *Ptr = CE->getOperand(0); if (!isa<GlobalValue>(Ptr) || !isa<StructType>(cast<PointerType>(Ptr->getType())->getElementType())) - return NULL; + return nullptr; // Second operand is zero. const ConstantInt *CI = dyn_cast_or_null<ConstantInt>(CE->getOperand(1)); if (!CI || !CI->isZero()) - return NULL; + return nullptr; // Third operand is offset. if (!isa<ConstantInt>(CE->getOperand(2))) - return NULL; + return nullptr; return CE; } @@ -1600,7 +1542,7 @@ void DwarfCompileUnit::createGlobalVariableDIE(DIGlobalVariable GV) { // If this is a static data member definition, some attributes belong // to the declaration DIE. - DIE *VariableDIE = NULL; + DIE *VariableDIE = nullptr; bool IsStaticMember = false; DIDerivedType SDMDecl = GV.getStaticDataMemberDeclaration(); if (SDMDecl.Verify()) { @@ -1618,24 +1560,24 @@ void DwarfCompileUnit::createGlobalVariableDIE(DIGlobalVariable GV) { DIE *ContextDIE = getOrCreateContextDIE(GVContext); // Add to map. - VariableDIE = createAndAddDIE(GV.getTag(), *ContextDIE, GV); + VariableDIE = &createAndAddDIE(GV.getTag(), *ContextDIE, GV); // Add name and type. - addString(VariableDIE, dwarf::DW_AT_name, GV.getDisplayName()); - addType(VariableDIE, GTy); + addString(*VariableDIE, dwarf::DW_AT_name, GV.getDisplayName()); + addType(*VariableDIE, GTy); // Add scoping info. if (!GV.isLocalToUnit()) - addFlag(VariableDIE, dwarf::DW_AT_external); + addFlag(*VariableDIE, dwarf::DW_AT_external); // Add line number info. - addSourceLine(VariableDIE, GV); + addSourceLine(*VariableDIE, GV); } // Add location. bool addToAccelTable = false; - DIE *VariableSpecDIE = NULL; - bool isGlobalVariable = GV.getGlobal() != NULL; + DIE *VariableSpecDIE = nullptr; + bool isGlobalVariable = GV.getGlobal() != nullptr; if (isGlobalVariable) { addToAccelTable = true; DIELoc *Loc = new (DIEValueAllocator) DIELoc(); @@ -1648,36 +1590,36 @@ void DwarfCompileUnit::createGlobalVariableDIE(DIGlobalVariable GV) { // Based on GCC's support for TLS: if (!DD->useSplitDwarf()) { // 1) Start with a constNu of the appropriate pointer size - addUInt(Loc, 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(Loc, dwarf::DW_FORM_udata, + addExpr(*Loc, dwarf::DW_FORM_udata, Asm->getObjFileLowering().getDebugThreadLocalSymbol(Sym)); } else { - addUInt(Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_GNU_const_index); - addUInt(Loc, dwarf::DW_FORM_udata, - DU->getAddrPoolIndex(Sym, /* TLS */ true)); + addUInt(*Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_GNU_const_index); + addUInt(*Loc, dwarf::DW_FORM_udata, + DD->getAddressPool().getIndex(Sym, /* TLS */ true)); } // 3) followed by a custom OP to make the debugger do a TLS lookup. - addUInt(Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_GNU_push_tls_address); + addUInt(*Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_GNU_push_tls_address); } else { DD->addArangeLabel(SymbolCU(this, Sym)); - addOpAddress(Loc, 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, *UnitDie); - addDIEEntry(VariableSpecDIE, dwarf::DW_AT_specification, VariableDIE); - addBlock(VariableSpecDIE, dwarf::DW_AT_location, Loc); + VariableSpecDIE = &createAndAddDIE(dwarf::DW_TAG_variable, UnitDie); + addDIEEntry(*VariableSpecDIE, dwarf::DW_AT_specification, *VariableDIE); + 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); + addFlag(*VariableDIE, dwarf::DW_AT_declaration); } else { - addBlock(VariableDIE, dwarf::DW_AT_location, Loc); + addBlock(*VariableDIE, dwarf::DW_AT_location, Loc); } // Add the linkage name. StringRef LinkageName = GV.getLinkageName(); @@ -1685,8 +1627,8 @@ void DwarfCompileUnit::createGlobalVariableDIE(DIGlobalVariable GV) { // From DWARF4: DIEs to which DW_AT_linkage_name may apply include: // TAG_common_block, TAG_constant, TAG_entry_point, TAG_subprogram and // TAG_variable. - addString(IsStaticMember && VariableSpecDIE ? VariableSpecDIE - : VariableDIE, + addString(IsStaticMember && VariableSpecDIE ? *VariableSpecDIE + : *VariableDIE, DD->getDwarfVersion() >= 4 ? dwarf::DW_AT_linkage_name : dwarf::DW_AT_MIPS_linkage_name, GlobalValue::getRealLinkageName(LinkageName)); @@ -1696,7 +1638,7 @@ void DwarfCompileUnit::createGlobalVariableDIE(DIGlobalVariable GV) { // emitting AT_const_value multiple times, we only add AT_const_value when // it is not a static member. if (!IsStaticMember) - addConstantValue(VariableDIE, CI, isUnsignedDIType(DD, GTy)); + addConstantValue(*VariableDIE, CI, GTy); } else if (const ConstantExpr *CE = getMergedGlobalExpr(GV->getOperand(11))) { addToAccelTable = true; // GV is a merged global. @@ -1704,34 +1646,35 @@ void DwarfCompileUnit::createGlobalVariableDIE(DIGlobalVariable GV) { Value *Ptr = CE->getOperand(0); 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); + 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(Loc, dwarf::DW_FORM_udata, + addUInt(*Loc, dwarf::DW_FORM_udata, Asm->getDataLayout().getIndexedOffset(Ptr->getType(), Idx)); - addUInt(Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_plus); - addBlock(VariableDIE, dwarf::DW_AT_location, Loc); + addUInt(*Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_plus); + addBlock(*VariableDIE, dwarf::DW_AT_location, Loc); } if (addToAccelTable) { - DIE *AddrDIE = VariableSpecDIE ? VariableSpecDIE : VariableDIE; - addAccelName(GV.getName(), AddrDIE); + DIE &AddrDIE = VariableSpecDIE ? *VariableSpecDIE : *VariableDIE; + DD->addAccelName(GV.getName(), AddrDIE); // If the linkage name is different than the name, go ahead and output // that as well into the name table. if (GV.getLinkageName() != "" && GV.getName() != GV.getLinkageName()) - addAccelName(GV.getLinkageName(), AddrDIE); + DD->addAccelName(GV.getLinkageName(), AddrDIE); } if (!GV.isLocalToUnit()) - addGlobalName(GV.getName(), VariableSpecDIE ? VariableSpecDIE : VariableDIE, + addGlobalName(GV.getName(), + VariableSpecDIE ? *VariableSpecDIE : *VariableDIE, GV.getContext()); } /// constructSubrangeDIE - Construct subrange DIE from DISubrange. 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); + DIE &DW_Subrange = createAndAddDIE(dwarf::DW_TAG_subrange_type, Buffer); + addDIEEntry(DW_Subrange, dwarf::DW_AT_type, *IndexTy); // The LowerBound value defines the lower bounds which is typically zero for // C/C++. The Count value is the number of elements. Values are 64 bit. If @@ -1756,10 +1699,10 @@ void DwarfUnit::constructSubrangeDIE(DIE &Buffer, DISubrange SR, DIE *IndexTy) { /// constructArrayTypeDIE - Construct array type DIE from DICompositeType. void DwarfUnit::constructArrayTypeDIE(DIE &Buffer, DICompositeType CTy) { if (CTy.isVector()) - addFlag(&Buffer, dwarf::DW_AT_GNU_vector); + addFlag(Buffer, dwarf::DW_AT_GNU_vector); // Emit the element type. - addType(&Buffer, resolve(CTy.getTypeDerivedFrom())); + addType(Buffer, resolve(CTy.getTypeDerivedFrom())); // Get an anonymous type for index type. // FIXME: This type should be passed down from the front end @@ -1767,10 +1710,10 @@ void DwarfUnit::constructArrayTypeDIE(DIE &Buffer, DICompositeType CTy) { DIE *IdxTy = getIndexTyDie(); if (!IdxTy) { // 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, + 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_unsigned); setIndexTyDie(IdxTy); } @@ -1792,7 +1735,7 @@ void DwarfUnit::constructEnumTypeDIE(DIE &Buffer, DICompositeType CTy) { for (unsigned i = 0, N = Elements.getNumElements(); i < N; ++i) { DIEnumerator Enum(Elements.getElement(i)); if (Enum.isEnumerator()) { - DIE *Enumerator = createAndAddDIE(dwarf::DW_TAG_enumerator, Buffer); + DIE &Enumerator = createAndAddDIE(dwarf::DW_TAG_enumerator, Buffer); StringRef Name = Enum.getName(); addString(Enumerator, dwarf::DW_AT_name, Name); int64_t Value = Enum.getEnumValue(); @@ -1802,8 +1745,8 @@ void DwarfUnit::constructEnumTypeDIE(DIE &Buffer, DICompositeType CTy) { } DIType DTy = resolve(CTy.getTypeDerivedFrom()); if (DTy) { - addType(&Buffer, DTy); - addFlag(&Buffer, dwarf::DW_AT_enum_class); + addType(Buffer, DTy); + addFlag(Buffer, dwarf::DW_AT_enum_class); } } @@ -1813,48 +1756,51 @@ void DwarfUnit::constructContainingTypeDIEs() { for (DenseMap<DIE *, const MDNode *>::iterator CI = ContainingTypeMap.begin(), CE = ContainingTypeMap.end(); CI != CE; ++CI) { - DIE *SPDie = CI->first; + DIE &SPDie = *CI->first; DIDescriptor D(CI->second); if (!D) continue; DIE *NDie = getDIE(D); if (!NDie) continue; - addDIEEntry(SPDie, dwarf::DW_AT_containing_type, NDie); + addDIEEntry(SPDie, dwarf::DW_AT_containing_type, *NDie); } } /// constructVariableDIE - Construct a DIE for the given DbgVariable. -DIE *DwarfUnit::constructVariableDIE(DbgVariable &DV, bool isScopeAbstract) { +std::unique_ptr<DIE> DwarfUnit::constructVariableDIE(DbgVariable &DV, + bool Abstract) { + auto D = constructVariableDIEImpl(DV, Abstract); + DV.setDIE(*D); + return D; +} + +std::unique_ptr<DIE> DwarfUnit::constructVariableDIEImpl(const DbgVariable &DV, + bool Abstract) { StringRef Name = DV.getName(); // Define variable debug information entry. - DIE *VariableDie = new DIE(DV.getTag()); + auto VariableDie = make_unique<DIE>(DV.getTag()); DbgVariable *AbsVar = DV.getAbstractVariable(); - DIE *AbsDIE = AbsVar ? AbsVar->getDIE() : NULL; - if (AbsDIE) - addDIEEntry(VariableDie, dwarf::DW_AT_abstract_origin, AbsDIE); + if (AbsVar && AbsVar->getDIE()) + addDIEEntry(*VariableDie, dwarf::DW_AT_abstract_origin, *AbsVar->getDIE()); else { if (!Name.empty()) - addString(VariableDie, dwarf::DW_AT_name, Name); - addSourceLine(VariableDie, DV.getVariable()); - addType(VariableDie, DV.getType()); + addString(*VariableDie, dwarf::DW_AT_name, Name); + addSourceLine(*VariableDie, DV.getVariable()); + addType(*VariableDie, DV.getType()); + if (DV.isArtificial()) + addFlag(*VariableDie, dwarf::DW_AT_artificial); } - if (DV.isArtificial()) - addFlag(VariableDie, dwarf::DW_AT_artificial); - - if (isScopeAbstract) { - DV.setDIE(VariableDie); + if (Abstract) return VariableDie; - } // Add variable address. unsigned Offset = DV.getDotDebugLocOffset(); if (Offset != ~0U) { - addLocationList(VariableDie, dwarf::DW_AT_location, Offset); - DV.setDIE(VariableDie); + addLocationList(*VariableDie, dwarf::DW_AT_location, Offset); return VariableDie; } @@ -1867,38 +1813,36 @@ DIE *DwarfUnit::constructVariableDIE(DbgVariable &DV, bool isScopeAbstract) { if (DVInsn->getOperand(1).isImm()) { MachineLocation Location(RegOp.getReg(), DVInsn->getOperand(1).getImm()); - addVariableAddress(DV, VariableDie, Location); + addVariableAddress(DV, *VariableDie, Location); } else if (RegOp.getReg()) - addVariableAddress(DV, VariableDie, MachineLocation(RegOp.getReg())); + addVariableAddress(DV, *VariableDie, MachineLocation(RegOp.getReg())); } else if (DVInsn->getOperand(0).isImm()) - addConstantValue(VariableDie, DVInsn->getOperand(0), DV.getType()); + addConstantValue(*VariableDie, DVInsn->getOperand(0), DV.getType()); else if (DVInsn->getOperand(0).isFPImm()) - addConstantFPValue(VariableDie, DVInsn->getOperand(0)); + addConstantFPValue(*VariableDie, DVInsn->getOperand(0)); else if (DVInsn->getOperand(0).isCImm()) - addConstantValue(VariableDie, DVInsn->getOperand(0).getCImm(), - isUnsignedDIType(DD, DV.getType())); + addConstantValue(*VariableDie, DVInsn->getOperand(0).getCImm(), + DV.getType()); - DV.setDIE(VariableDie); return VariableDie; - } else { - // .. else use frame index. - int FI = DV.getFrameIndex(); - if (FI != ~0) { - unsigned FrameReg = 0; - const TargetFrameLowering *TFI = Asm->TM.getFrameLowering(); - int Offset = TFI->getFrameIndexReference(*Asm->MF, FI, FrameReg); - MachineLocation Location(FrameReg, Offset); - addVariableAddress(DV, VariableDie, Location); - } } - DV.setDIE(VariableDie); + // .. else use frame index. + int FI = DV.getFrameIndex(); + if (FI != ~0) { + unsigned FrameReg = 0; + const TargetFrameLowering *TFI = Asm->TM.getFrameLowering(); + int Offset = TFI->getFrameIndexReference(*Asm->MF, FI, FrameReg); + MachineLocation Location(FrameReg, Offset); + addVariableAddress(DV, *VariableDie, Location); + } + return VariableDie; } /// constructMemberDIE - Construct member DIE from DIDerivedType. void DwarfUnit::constructMemberDIE(DIE &Buffer, DIDerivedType DT) { - DIE *MemberDie = createAndAddDIE(DT.getTag(), Buffer); + DIE &MemberDie = createAndAddDIE(DT.getTag(), Buffer); StringRef Name = DT.getName(); if (!Name.empty()) addString(MemberDie, dwarf::DW_AT_name, Name); @@ -1914,13 +1858,13 @@ void DwarfUnit::constructMemberDIE(DIE &Buffer, DIDerivedType DT) { // BaseAddr = ObAddr + *((*ObAddr) - Offset) 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); - addUInt(VBaseLocationDie, dwarf::DW_FORM_udata, DT.getOffsetInBits()); - addUInt(VBaseLocationDie, dwarf::DW_FORM_data1, dwarf::DW_OP_minus); - addUInt(VBaseLocationDie, dwarf::DW_FORM_data1, dwarf::DW_OP_deref); - addUInt(VBaseLocationDie, dwarf::DW_FORM_data1, dwarf::DW_OP_plus); + 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); + addUInt(*VBaseLocationDie, dwarf::DW_FORM_udata, DT.getOffsetInBits()); + addUInt(*VBaseLocationDie, dwarf::DW_FORM_data1, dwarf::DW_OP_minus); + addUInt(*VBaseLocationDie, dwarf::DW_FORM_data1, dwarf::DW_OP_deref); + addUInt(*VBaseLocationDie, dwarf::DW_FORM_data1, dwarf::DW_OP_plus); addBlock(MemberDie, dwarf::DW_AT_data_member_location, VBaseLocationDie); } else { @@ -1953,8 +1897,8 @@ void DwarfUnit::constructMemberDIE(DIE &Buffer, DIDerivedType DT) { 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); + 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, @@ -1978,8 +1922,8 @@ void DwarfUnit::constructMemberDIE(DIE &Buffer, DIDerivedType DT) { // Objective-C properties. if (MDNode *PNode = DT.getObjCProperty()) if (DIEEntry *PropertyDie = getDIEEntry(PNode)) - MemberDie->addValue(dwarf::DW_AT_APPLE_property, dwarf::DW_FORM_ref4, - PropertyDie); + MemberDie.addValue(dwarf::DW_AT_APPLE_property, dwarf::DW_FORM_ref4, + PropertyDie); if (DT.isArtificial()) addFlag(MemberDie, dwarf::DW_AT_artificial); @@ -1988,7 +1932,7 @@ void DwarfUnit::constructMemberDIE(DIE &Buffer, DIDerivedType DT) { /// getOrCreateStaticMemberDIE - Create new DIE for C++ static member. DIE *DwarfUnit::getOrCreateStaticMemberDIE(DIDerivedType DT) { if (!DT.Verify()) - return NULL; + return nullptr; // Construct the context before querying for the existence of the DIE in case // such construction creates the DIE. @@ -1996,11 +1940,10 @@ DIE *DwarfUnit::getOrCreateStaticMemberDIE(DIDerivedType DT) { assert(dwarf::isType(ContextDIE->getTag()) && "Static member should belong to a type."); - DIE *StaticMemberDIE = getDIE(DT); - if (StaticMemberDIE) + if (DIE *StaticMemberDIE = getDIE(DT)) return StaticMemberDIE; - StaticMemberDIE = createAndAddDIE(DT.getTag(), *ContextDIE, DT); + DIE &StaticMemberDIE = createAndAddDIE(DT.getTag(), *ContextDIE, DT); DIType Ty = resolve(DT.getTypeDerivedFrom()); @@ -2023,11 +1966,11 @@ DIE *DwarfUnit::getOrCreateStaticMemberDIE(DIDerivedType DT) { dwarf::DW_ACCESS_public); if (const ConstantInt *CI = dyn_cast_or_null<ConstantInt>(DT.getConstant())) - addConstantValue(StaticMemberDIE, CI, isUnsignedDIType(DD, Ty)); + addConstantValue(StaticMemberDIE, CI, Ty); if (const ConstantFP *CFP = dyn_cast_or_null<ConstantFP>(DT.getConstant())) addConstantFPValue(StaticMemberDIE, CFP); - return StaticMemberDIE; + return &StaticMemberDIE; } void DwarfUnit::emitHeader(const MCSymbol *ASectionSym) const { @@ -2072,7 +2015,7 @@ void DwarfCompileUnit::initStmtList(MCSymbol *DwarfLineSectionSym) { MCSymbol *LineTableStartSym = Asm->OutStreamer.getDwarfLineTableSymbol(getUniqueID()); - stmtListIndex = UnitDie->getValues().size(); + 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 @@ -2080,16 +2023,16 @@ void DwarfCompileUnit::initStmtList(MCSymbol *DwarfLineSectionSym) { // 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); + addSectionLabel(UnitDie, dwarf::DW_AT_stmt_list, LineTableStartSym); else - addSectionDelta(UnitDie.get(), dwarf::DW_AT_stmt_list, LineTableStartSym, + addSectionDelta(UnitDie, 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]); + UnitDie.getAbbrev().getData()[stmtListIndex].getForm(), + UnitDie.getValues()[stmtListIndex]); } void DwarfTypeUnit::emitHeader(const MCSymbol *ASectionSym) const { @@ -2114,5 +2057,4 @@ void DwarfTypeUnit::initSection(const MCSection *Section) { 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/DwarfUnit.h b/lib/CodeGen/AsmPrinter/DwarfUnit.h index ef713f7..acb7528 100644 --- a/lib/CodeGen/AsmPrinter/DwarfUnit.h +++ b/lib/CodeGen/AsmPrinter/DwarfUnit.h @@ -73,7 +73,7 @@ protected: DICompileUnit CUNode; /// Unit debug information entry. - const std::unique_ptr<DIE> UnitDie; + DIE UnitDie; /// Offset of the UnitDie from beginning of debug info section. unsigned DebugInfoOffset; @@ -102,18 +102,6 @@ protected: /// GlobalTypes - A map of globally visible types for this unit. StringMap<const DIE *> GlobalTypes; - /// AccelNames - A map of names for the name accelerator table. - 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; @@ -150,20 +138,17 @@ protected: /// 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, + DwarfUnit(unsigned UID, dwarf::Tag, DICompileUnit CU, AsmPrinter *A, DwarfDebug *DW, DwarfFile *DWU); public: virtual ~DwarfUnit(); /// Set the skeleton unit associated with this unit. - void setSkeleton(DwarfUnit *Skel) { Skeleton = Skel; } + void setSkeleton(DwarfUnit &Skel) { Skeleton = &Skel; } /// Get the skeleton unit associated with this unit. DwarfUnit *getSkeleton() const { return Skeleton; } @@ -179,7 +164,6 @@ public: Asm->GetTempSymbol(Section->getLabelBeginName(), getUniqueID()); this->LabelEnd = Asm->GetTempSymbol(Section->getLabelEndName(), getUniqueID()); - this->LabelRange = Asm->GetTempSymbol("gnu_ranges", getUniqueID()); } const MCSection *getSection() const { @@ -218,38 +202,19 @@ public: return LabelEnd; } - MCSymbol *getLabelRange() const { - assert(Section); - return LabelRange; - } - // Accessors. unsigned getUniqueID() const { return UniqueID; } uint16_t getLanguage() const { return CUNode.getLanguage(); } DICompileUnit getCUNode() const { return CUNode; } - DIE *getUnitDie() const { return UnitDie.get(); } + DIE &getUnitDie() { return UnitDie; } const StringMap<const DIE *> &getGlobalNames() const { return GlobalNames; } const StringMap<const DIE *> &getGlobalTypes() const { return GlobalTypes; } - const StringMap<std::vector<const DIE *> > &getAccelNames() const { - return AccelNames; - } - const StringMap<std::vector<const DIE *> > &getAccelObjC() const { - return AccelObjC; - } - const StringMap<std::vector<const DIE *> > &getAccelNamespace() const { - return AccelNamespace; - } - const StringMap<std::vector<std::pair<const DIE *, unsigned> > > & - getAccelTypes() const { - return AccelTypes; - } - unsigned getDebugInfoOffset() const { return DebugInfoOffset; } void setDebugInfoOffset(unsigned DbgInfoOff) { DebugInfoOffset = DbgInfoOff; } /// hasContent - Return true if this compile unit has something to write out. - bool hasContent() const { return !UnitDie->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); @@ -273,19 +238,10 @@ public: /// addGlobalName - Add a new global entity to the compile unit. /// - void addGlobalName(StringRef Name, DIE *Die, DIScope Context); - - /// addAccelName - Add a new name to the name accelerator table. - void addAccelName(StringRef Name, const DIE *Die); - - /// addAccelObjC - Add a new name to the ObjC accelerator table. - void addAccelObjC(StringRef Name, const DIE *Die); + void addGlobalName(StringRef Name, DIE &Die, DIScope Context); /// addAccelNamespace - Add a new name to the namespace accelerator table. - void addAccelNamespace(StringRef Name, const DIE *Die); - - /// addAccelType - Add a new type to the type accelerator table. - void addAccelType(StringRef Name, std::pair<const DIE *, unsigned> Die); + void addAccelNamespace(StringRef Name, const DIE &Die); /// getDIE - Returns the debug information entry map slot for the /// specified debug variable. We delegate the request to DwarfDebug @@ -303,118 +259,116 @@ public: /// kept in DwarfDebug. void insertDIE(DIDescriptor Desc, DIE *D); - /// addDie - Adds or interns the DIE to the compile unit. - /// - void addDie(DIE *Buffer) { UnitDie->addChild(Buffer); } - /// addFlag - Add a flag that is true to the DIE. - void addFlag(DIE *Die, dwarf::Attribute Attribute); + 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, + void addUInt(DIE &Die, dwarf::Attribute Attribute, Optional<dwarf::Form> Form, uint64_t Integer); - void addUInt(DIE *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, + void addSInt(DIE &Die, dwarf::Attribute Attribute, Optional<dwarf::Form> Form, int64_t Integer); - void addSInt(DIELoc *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); + 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, + void addLocalString(DIE &Die, dwarf::Attribute Attribute, const StringRef Str); /// addExpr - Add a Dwarf expression attribute data and value. - void addExpr(DIELoc *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, + void addLabel(DIE &Die, dwarf::Attribute Attribute, dwarf::Form Form, const MCSymbol *Label); - void addLabel(DIELoc *Die, dwarf::Form Form, const MCSymbol *Label); + void addLabel(DIELoc &Die, dwarf::Form Form, const MCSymbol *Label); /// addLocationList - Add a Dwarf loclistptr attribute data and value. - void addLocationList(DIE *Die, dwarf::Attribute Attribute, unsigned Index); + void addLocationList(DIE &Die, dwarf::Attribute Attribute, unsigned Index); /// addSectionLabel - Add a Dwarf section label attribute data and value. /// - void addSectionLabel(DIE *Die, dwarf::Attribute Attribute, + 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); + 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(DIELoc *Die, const MCSymbol *Label); + void addOpAddress(DIELoc &Die, const MCSymbol *Label); /// addSectionDelta - Add a label delta attribute data and value. - void addSectionDelta(DIE *Die, dwarf::Attribute Attribute, const MCSymbol *Hi, + 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, + 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); + 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 addDIEEntry(DIE &Die, dwarf::Attribute Attribute, DIEEntry *Entry); - void addDIETypeSignature(DIE *Die, const DwarfTypeUnit &Type); + void addDIETypeSignature(DIE &Die, const DwarfTypeUnit &Type); /// addBlock - Add block data. - void addBlock(DIE *Die, dwarf::Attribute Attribute, DIELoc *Block); + void addBlock(DIE &Die, dwarf::Attribute Attribute, DIELoc *Block); /// addBlock - Add block data. - void addBlock(DIE *Die, dwarf::Attribute Attribute, DIEBlock *Block); + 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, + 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); - void addSourceLine(DIE *Die, DIType Ty); - void addSourceLine(DIE *Die, DINameSpace NS); - void addSourceLine(DIE *Die, DIObjCProperty Ty); + void addSourceLine(DIE &Die, DIVariable V); + void addSourceLine(DIE &Die, DIGlobalVariable G); + void addSourceLine(DIE &Die, DISubprogram SP); + void addSourceLine(DIE &Die, DIType Ty); + void addSourceLine(DIE &Die, DINameSpace NS); + void addSourceLine(DIE &Die, DIObjCProperty Ty); /// addAddress - Add an address attribute to a die based on the location /// provided. - void addAddress(DIE *Die, dwarf::Attribute Attribute, + 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); - void addConstantValue(DIE *Die, const ConstantInt *CI, bool Unsigned); - void addConstantValue(DIE *Die, const APInt &Val, bool Unsigned); + void addConstantValue(DIE &Die, const MachineOperand &MO, DIType Ty); + void addConstantValue(DIE &Die, const ConstantInt *CI, DIType Ty); + void addConstantValue(DIE &Die, const APInt &Val, DIType Ty); + void addConstantValue(DIE &Die, const APInt &Val, bool Unsigned); + void addConstantValue(DIE &Die, bool Unsigned, uint64_t Val); /// addConstantFPValue - Add constant value entry in variable DIE. - void addConstantFPValue(DIE *Die, const MachineOperand &MO); - void addConstantFPValue(DIE *Die, const ConstantFP *CFP); + void addConstantFPValue(DIE &Die, const MachineOperand &MO); + void addConstantFPValue(DIE &Die, const ConstantFP *CFP); /// addTemplateParams - Add template parameters in buffer. void addTemplateParams(DIE &Buffer, DIArray TParams); /// addRegisterOp - Add register operand. - void addRegisterOp(DIELoc *TheDie, unsigned Reg); + void addRegisterOp(DIELoc &TheDie, unsigned Reg); /// addRegisterOffset - Add register offset. - void addRegisterOffset(DIELoc *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, + void addComplexAddress(const DbgVariable &DV, DIE &Die, dwarf::Attribute Attribute, const MachineLocation &Location); @@ -424,19 +378,19 @@ 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, + void addBlockByrefAddress(const DbgVariable &DV, DIE &Die, dwarf::Attribute Attribute, const MachineLocation &Location); /// addVariableAddress - Add DW_AT_location attribute for a /// DbgVariable based on provided MachineLocation. - void addVariableAddress(const DbgVariable &DV, DIE *Die, + void addVariableAddress(const DbgVariable &DV, DIE &Die, MachineLocation Location); /// 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, + void addType(DIE &Entity, DIType Ty, dwarf::Attribute Attribute = dwarf::DW_AT_type); /// getOrCreateNameSpace - Create a DIE for DINameSpace. @@ -445,6 +399,8 @@ public: /// getOrCreateSubprogramDIE - Create new DIE using SP. DIE *getOrCreateSubprogramDIE(DISubprogram SP); + void applySubprogramAttributes(DISubprogram SP, DIE &SPDie); + /// getOrCreateTypeDIE - Find existing DIE or create new DIE for the /// given DIType. DIE *getOrCreateTypeDIE(const MDNode *N); @@ -460,14 +416,15 @@ public: void constructContainingTypeDIEs(); /// constructVariableDIE - Construct a DIE for the given DbgVariable. - DIE *constructVariableDIE(DbgVariable &DV, bool isScopeAbstract); + std::unique_ptr<DIE> constructVariableDIE(DbgVariable &DV, + bool Abstract = false); /// 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, + DIE &createAndAddDIE(unsigned Tag, DIE &Parent, DIDescriptor N = DIDescriptor()); /// Compute the size of a header for this unit, not including the initial @@ -483,6 +440,9 @@ public: virtual DwarfCompileUnit &getCU() = 0; + /// constructTypeDIE - Construct type DIE from DICompositeType. + void constructTypeDIE(DIE &Buffer, DICompositeType CTy); + protected: /// getOrCreateStaticMemberDIE - Create new static data member DIE. DIE *getOrCreateStaticMemberDIE(DIDerivedType DT); @@ -492,15 +452,17 @@ protected: virtual unsigned getOrCreateSourceID(StringRef File, StringRef Directory) = 0; private: + /// \brief Construct a DIE for the given DbgVariable without initializing the + /// DbgVariable's DIE reference. + std::unique_ptr<DIE> constructVariableDIEImpl(const DbgVariable &DV, + bool Abstract); + /// constructTypeDIE - Construct basic type die from DIBasicType. void constructTypeDIE(DIE &Buffer, DIBasicType BTy); /// constructTypeDIE - Construct derived type die from DIDerivedType. void constructTypeDIE(DIE &Buffer, DIDerivedType DTy); - /// constructTypeDIE - Construct type DIE from DICompositeType. - void constructTypeDIE(DIE &Buffer, DICompositeType CTy); - /// constructSubrangeDIE - Construct subrange DIE from DISubrange. void constructSubrangeDIE(DIE &Buffer, DISubrange SR, DIE *IndexTy); @@ -547,7 +509,7 @@ private: /// createDIEEntry - Creates a new DIEEntry to be a proxy for a debug /// information entry. - DIEEntry *createDIEEntry(DIE *Entry); + DIEEntry *createDIEEntry(DIE &Entry); /// resolve - Look in the DwarfDebug map for the MDNode that /// corresponds to the reference. @@ -557,7 +519,7 @@ private: /// 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); + void updateAcceleratorTables(DIScope Context, DIType Ty, const DIE &TyDIE); }; class DwarfCompileUnit : public DwarfUnit { @@ -566,7 +528,7 @@ class DwarfCompileUnit : public DwarfUnit { unsigned stmtListIndex; public: - DwarfCompileUnit(unsigned UID, DIE *D, DICompileUnit Node, AsmPrinter *A, + DwarfCompileUnit(unsigned UID, DICompileUnit Node, AsmPrinter *A, DwarfDebug *DW, DwarfFile *DWU); void initStmtList(MCSymbol *DwarfLineSectionSym); @@ -579,12 +541,12 @@ public: /// 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, + 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, + void addLocalLabelAddress(DIE &Die, dwarf::Attribute Attribute, const MCSymbol *Label); DwarfCompileUnit &getCU() override { return *this; } @@ -600,7 +562,7 @@ private: MCDwarfDwoLineTable *SplitLineTable; public: - DwarfTypeUnit(unsigned UID, DIE *D, DwarfCompileUnit &CU, AsmPrinter *A, + DwarfTypeUnit(unsigned UID, DwarfCompileUnit &CU, AsmPrinter *A, DwarfDebug *DW, DwarfFile *DWU, MCDwarfDwoLineTable *SplitLineTable = nullptr); diff --git a/lib/CodeGen/AsmPrinter/WinCodeViewLineTables.cpp b/lib/CodeGen/AsmPrinter/WinCodeViewLineTables.cpp index 50b2ca8..2212941 100644 --- a/lib/CodeGen/AsmPrinter/WinCodeViewLineTables.cpp +++ b/lib/CodeGen/AsmPrinter/WinCodeViewLineTables.cpp @@ -29,7 +29,7 @@ StringRef WinCodeViewLineTables::getFullFilepath(const MDNode *S) { StringRef Dir = Scope.getDirectory(), Filename = Scope.getFilename(); char *&Result = DirAndFilenameToFilepathMap[std::make_pair(Dir, Filename)]; - if (Result != 0) + if (Result) return Result; // Clang emits directory and relative filename info into the IR, but CodeView @@ -102,7 +102,7 @@ void WinCodeViewLineTables::maybeRecordLocation(DebugLoc DL, } WinCodeViewLineTables::WinCodeViewLineTables(AsmPrinter *AP) - : Asm(0), CurFn(0) { + : Asm(nullptr), CurFn(nullptr) { MachineModuleInfo *MMI = AP->MMI; // If module doesn't have named metadata anchors or COFF debug section @@ -171,7 +171,7 @@ void WinCodeViewLineTables::emitDebugInfoForFunction(const Function *GV) { EmitLabelDiff(Asm->OutStreamer, Fn, FI.End); // PC-to-linenumber lookup table: - MCSymbol *FileSegmentEnd = 0; + MCSymbol *FileSegmentEnd = nullptr; for (size_t J = 0, F = FI.Instrs.size(); J != F; ++J) { MCSymbol *Instr = FI.Instrs[J]; assert(InstrInfo.count(Instr)); @@ -216,7 +216,7 @@ void WinCodeViewLineTables::endModule() { if (FnDebugInfo.empty()) return; - assert(Asm != 0); + assert(Asm != nullptr); Asm->OutStreamer.SwitchSection( Asm->getObjFileLowering().getCOFFDebugSymbolsSection()); Asm->EmitInt32(COFF::DEBUG_SECTION_MAGIC); @@ -277,20 +277,19 @@ void WinCodeViewLineTables::beginFunction(const MachineFunction *MF) { // 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()) + for (const auto &MBB : *MF) { + if (!PrologEndLoc.isUnknown()) + break; + for (const auto &MI : MBB) { + 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(); + if (!MI.getFlag(MachineInstr::FrameSetup) && + (!MI.getDebugLoc().isUnknown())) { + PrologEndLoc = MI.getDebugLoc(); break; } EmptyPrologue = false; @@ -321,7 +320,7 @@ void WinCodeViewLineTables::endFunction(const MachineFunction *MF) { Asm->OutStreamer.EmitLabel(FunctionEndSym); CurFn->End = FunctionEndSym; } - CurFn = 0; + CurFn = nullptr; } void WinCodeViewLineTables::beginInstruction(const MachineInstr *MI) { diff --git a/lib/CodeGen/AsmPrinter/WinCodeViewLineTables.h b/lib/CodeGen/AsmPrinter/WinCodeViewLineTables.h index a7a6205..0734d97 100644 --- a/lib/CodeGen/AsmPrinter/WinCodeViewLineTables.h +++ b/lib/CodeGen/AsmPrinter/WinCodeViewLineTables.h @@ -38,7 +38,7 @@ class WinCodeViewLineTables : public AsmPrinterHandler { struct FunctionInfo { SmallVector<MCSymbol *, 10> Instrs; MCSymbol *End; - FunctionInfo() : End(0) {} + FunctionInfo() : End(nullptr) {} } *CurFn; typedef DenseMap<const Function *, FunctionInfo> FnDebugInfoTy; @@ -104,7 +104,7 @@ class WinCodeViewLineTables : public AsmPrinterHandler { void maybeRecordLocation(DebugLoc DL, const MachineFunction *MF); void clear() { - assert(CurFn == 0); + assert(CurFn == nullptr); FileNameRegistry.clear(); InstrInfo.clear(); } |