diff options
Diffstat (limited to 'lib/CodeGen/AsmPrinter')
39 files changed, 2466 insertions, 2051 deletions
diff --git a/lib/CodeGen/AsmPrinter/ARMException.cpp b/lib/CodeGen/AsmPrinter/ARMException.cpp index 251f5ef..66c6c63 100644 --- a/lib/CodeGen/AsmPrinter/ARMException.cpp +++ b/lib/CodeGen/AsmPrinter/ARMException.cpp @@ -108,7 +108,7 @@ void ARMException::endFunction(const MachineFunction *) { } void ARMException::emitTypeInfos(unsigned TTypeEncoding) { - const std::vector<const GlobalVariable *> &TypeInfos = MMI->getTypeInfos(); + const std::vector<const GlobalValue *> &TypeInfos = MMI->getTypeInfos(); const std::vector<unsigned> &FilterIds = MMI->getFilterIds(); bool VerboseAsm = Asm->OutStreamer.isVerboseAsm(); @@ -121,9 +121,9 @@ void ARMException::emitTypeInfos(unsigned TTypeEncoding) { Entry = TypeInfos.size(); } - for (std::vector<const GlobalVariable *>::const_reverse_iterator + for (std::vector<const GlobalValue *>::const_reverse_iterator I = TypeInfos.rbegin(), E = TypeInfos.rend(); I != E; ++I) { - const GlobalVariable *GV = *I; + const GlobalValue *GV = *I; if (VerboseAsm) Asm->OutStreamer.AddComment("TypeInfo " + Twine(Entry--)); Asm->EmitTTypeReference(GV, TTypeEncoding); diff --git a/lib/CodeGen/AsmPrinter/AddressPool.h b/lib/CodeGen/AsmPrinter/AddressPool.h index 42757d7..802e050 100644 --- a/lib/CodeGen/AsmPrinter/AddressPool.h +++ b/lib/CodeGen/AsmPrinter/AddressPool.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef CODEGEN_ASMPRINTER_ADDRESSPOOL_H__ -#define CODEGEN_ASMPRINTER_ADDRESSPOOL_H__ +#ifndef LLVM_LIB_CODEGEN_ASMPRINTER_ADDRESSPOOL_H +#define LLVM_LIB_CODEGEN_ASMPRINTER_ADDRESSPOOL_H #include "llvm/ADT/DenseMap.h" diff --git a/lib/CodeGen/AsmPrinter/Android.mk b/lib/CodeGen/AsmPrinter/Android.mk index 083cc0d..cb8e96a 100644 --- a/lib/CodeGen/AsmPrinter/Android.mk +++ b/lib/CodeGen/AsmPrinter/Android.mk @@ -11,6 +11,7 @@ codegen_asmprinter_SRC_FILES := \ DIEHash.cpp \ DwarfAccelTable.cpp \ DwarfCFIException.cpp \ + DwarfCompileUnit.cpp \ DwarfDebug.cpp \ DwarfFile.cpp \ DwarfStringPool.cpp \ diff --git a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index f80fdea..8a32713 100644 --- a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -14,11 +14,13 @@ #include "llvm/CodeGen/AsmPrinter.h" #include "DwarfDebug.h" #include "DwarfException.h" +#include "Win64Exception.h" #include "WinCodeViewLineTables.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/Statistic.h" #include "llvm/Analysis/ConstantFolding.h" #include "llvm/Analysis/JumpInstrTableInfo.h" +#include "llvm/CodeGen/Analysis.h" #include "llvm/CodeGen/GCMetadataPrinter.h" #include "llvm/CodeGen/MachineConstantPool.h" #include "llvm/CodeGen/MachineFrameInfo.h" @@ -49,7 +51,6 @@ #include "llvm/Target/TargetLoweringObjectFile.h" #include "llvm/Target/TargetRegisterInfo.h" #include "llvm/Target/TargetSubtargetInfo.h" -#include "llvm/Transforms/Utils/GlobalStatus.h" using namespace llvm; #define DEBUG_TYPE "asm-printer" @@ -98,11 +99,10 @@ static unsigned getGVAlignmentLog2(const GlobalValue *GV, const DataLayout &TD, } AsmPrinter::AsmPrinter(TargetMachine &tm, MCStreamer &Streamer) - : MachineFunctionPass(ID), - TM(tm), MAI(tm.getMCAsmInfo()), MII(tm.getInstrInfo()), - OutContext(Streamer.getContext()), - OutStreamer(Streamer), - LastMI(nullptr), LastFn(0), Counter(~0U), SetCounter(0) { + : MachineFunctionPass(ID), TM(tm), MAI(tm.getMCAsmInfo()), + MII(tm.getSubtargetImpl()->getInstrInfo()), + OutContext(Streamer.getContext()), OutStreamer(Streamer), LastMI(nullptr), + LastFn(0), Counter(~0U), SetCounter(0) { DD = nullptr; MMI = nullptr; LI = nullptr; MF = nullptr; CurrentFnSym = CurrentFnSymForSize = nullptr; GCMetadataPrinters = nullptr; @@ -129,12 +129,12 @@ unsigned AsmPrinter::getFunctionNumber() const { } const TargetLoweringObjectFile &AsmPrinter::getObjFileLowering() const { - return TM.getTargetLowering()->getObjFileLowering(); + return TM.getSubtargetImpl()->getTargetLowering()->getObjFileLowering(); } /// getDataLayout - Return information about data layout. const DataLayout &AsmPrinter::getDataLayout() const { - return *TM.getDataLayout(); + return *TM.getSubtargetImpl()->getDataLayout(); } const MCSubtargetInfo &AsmPrinter::getSubtargetInfo() const { @@ -173,9 +173,9 @@ bool AsmPrinter::doInitialization(Module &M) { const_cast<TargetLoweringObjectFile&>(getObjFileLowering()) .Initialize(OutContext, TM); - OutStreamer.InitSections(); + OutStreamer.InitSections(false); - Mang = new Mangler(TM.getDataLayout()); + Mang = new Mangler(TM.getSubtargetImpl()->getDataLayout()); // Emit the version-min deplyment target directive if needed. // @@ -222,14 +222,12 @@ bool AsmPrinter::doInitialization(Module &M) { } if (MAI->doesSupportDebugInformation()) { - if (Triple(TM.getTargetTriple()).isKnownWindowsMSVCEnvironment()) { + if (Triple(TM.getTargetTriple()).isKnownWindowsMSVCEnvironment()) Handlers.push_back(HandlerInfo(new WinCodeViewLineTables(this), DbgTimerName, CodeViewLineTablesGroupName)); - } else { - DD = new DwarfDebug(this, &M); - Handlers.push_back(HandlerInfo(DD, DbgTimerName, DWARFGroupName)); - } + DD = new DwarfDebug(this, &M); + Handlers.push_back(HandlerInfo(DD, DbgTimerName, DWARFGroupName)); } EHStreamer *ES = nullptr; @@ -243,8 +241,13 @@ bool AsmPrinter::doInitialization(Module &M) { case ExceptionHandling::ARM: ES = new ARMException(this); break; - case ExceptionHandling::WinEH: - ES = new Win64Exception(this); + case ExceptionHandling::ItaniumWinEH: + switch (MAI->getWinEHEncodingType()) { + default: llvm_unreachable("unsupported unwinding information encoding"); + case WinEH::EncodingType::Itanium: + ES = new Win64Exception(this); + break; + } break; } if (ES) @@ -253,33 +256,10 @@ bool AsmPrinter::doInitialization(Module &M) { } static bool canBeHidden(const GlobalValue *GV, const MCAsmInfo &MAI) { - GlobalValue::LinkageTypes Linkage = GV->getLinkage(); - if (Linkage != GlobalValue::LinkOnceODRLinkage) - return false; - if (!MAI.hasWeakDefCanBeHiddenDirective()) return false; - if (GV->hasUnnamedAddr()) - return true; - - // This is only used for MachO, so right now it doesn't really matter how - // we handle alias. Revisit this once the MachO linker implements aliases. - if (isa<GlobalAlias>(GV)) - return false; - - // If it is a non constant variable, it needs to be uniqued across shared - // objects. - if (const GlobalVariable *Var = dyn_cast<GlobalVariable>(GV)) { - if (!Var->isConstant()) - return false; - } - - GlobalStatus GS; - if (!GlobalStatus::analyzeGlobal(GV, GS) && !GS.IsCompared) - return true; - - return false; + return canBeOmittedFromSymbolTable(GV); } void AsmPrinter::EmitLinkage(const GlobalValue *GV, MCSymbol *GVSym) const { @@ -361,7 +341,7 @@ void AsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) { SectionKind GVKind = TargetLoweringObjectFile::getKindForGlobal(GV, TM); - const DataLayout *DL = TM.getDataLayout(); + const DataLayout *DL = TM.getSubtargetImpl()->getDataLayout(); uint64_t Size = DL->getTypeAllocSize(GV->getType()->getElementType()); // If the alignment is specified, we *must* obey it. Overaligning a global @@ -578,20 +558,24 @@ static void emitComments(const MachineInstr &MI, raw_ostream &CommentOS) { // We assume a single instruction only has a spill or reload, not // both. const MachineMemOperand *MMO; - if (TM.getInstrInfo()->isLoadFromStackSlotPostFE(&MI, FI)) { + if (TM.getSubtargetImpl()->getInstrInfo()->isLoadFromStackSlotPostFE(&MI, + FI)) { if (FrameInfo->isSpillSlotObjectIndex(FI)) { MMO = *MI.memoperands_begin(); CommentOS << MMO->getSize() << "-byte Reload\n"; } - } else if (TM.getInstrInfo()->hasLoadFromStackSlot(&MI, MMO, FI)) { + } else if (TM.getSubtargetImpl()->getInstrInfo()->hasLoadFromStackSlot( + &MI, MMO, FI)) { if (FrameInfo->isSpillSlotObjectIndex(FI)) CommentOS << MMO->getSize() << "-byte Folded Reload\n"; - } else if (TM.getInstrInfo()->isStoreToStackSlotPostFE(&MI, FI)) { + } else if (TM.getSubtargetImpl()->getInstrInfo()->isStoreToStackSlotPostFE( + &MI, FI)) { if (FrameInfo->isSpillSlotObjectIndex(FI)) { MMO = *MI.memoperands_begin(); CommentOS << MMO->getSize() << "-byte Spill\n"; } - } else if (TM.getInstrInfo()->hasStoreToStackSlot(&MI, MMO, FI)) { + } else if (TM.getSubtargetImpl()->getInstrInfo()->hasStoreToStackSlot( + &MI, MMO, FI)) { if (FrameInfo->isSpillSlotObjectIndex(FI)) CommentOS << MMO->getSize() << "-byte Folded Spill\n"; } @@ -605,8 +589,9 @@ static void emitComments(const MachineInstr &MI, raw_ostream &CommentOS) { /// that is an implicit def. void AsmPrinter::emitImplicitDef(const MachineInstr *MI) const { unsigned RegNo = MI->getOperand(0).getReg(); - OutStreamer.AddComment(Twine("implicit-def: ") + - TM.getRegisterInfo()->getName(RegNo)); + OutStreamer.AddComment( + Twine("implicit-def: ") + + TM.getSubtargetImpl()->getRegisterInfo()->getName(RegNo)); OutStreamer.AddBlankLine(); } @@ -616,7 +601,7 @@ static void emitKill(const MachineInstr *MI, AsmPrinter &AP) { const MachineOperand &Op = MI->getOperand(i); assert(Op.isReg() && "KILL instruction must have only register operands"); Str += ' '; - Str += AP.TM.getRegisterInfo()->getName(Op.getReg()); + Str += AP.TM.getSubtargetImpl()->getRegisterInfo()->getName(Op.getReg()); Str += (Op.isDef() ? "<def>" : "<kill>"); } AP.OutStreamer.AddComment(Str); @@ -627,21 +612,27 @@ static void emitKill(const MachineInstr *MI, AsmPrinter &AP) { /// of DBG_VALUE, returning true if it was able to do so. A false return /// means the target will need to handle MI in EmitInstruction. static bool emitDebugValueComment(const MachineInstr *MI, AsmPrinter &AP) { - // This code handles only the 3-operand target-independent form. - if (MI->getNumOperands() != 3) + // This code handles only the 4-operand target-independent form. + if (MI->getNumOperands() != 4) return false; SmallString<128> Str; raw_svector_ostream OS(Str); OS << "DEBUG_VALUE: "; - DIVariable V(MI->getOperand(2).getMetadata()); + DIVariable V = MI->getDebugVariable(); if (V.getContext().isSubprogram()) { StringRef Name = DISubprogram(V.getContext()).getDisplayName(); if (!Name.empty()) OS << Name << ":"; } - OS << V.getName() << " <- "; + OS << V.getName(); + + DIExpression Expr = MI->getDebugExpression(); + if (Expr.isVariablePiece()) + OS << " [piece offset=" << Expr.getPieceOffset() + << " size=" << Expr.getPieceSize() << "]"; + OS << " <- "; // The second operand is only an offset if it's an immediate. bool Deref = MI->getOperand(0).isReg() && MI->getOperand(1).isImm(); @@ -672,7 +663,8 @@ static bool emitDebugValueComment(const MachineInstr *MI, AsmPrinter &AP) { Reg = MI->getOperand(0).getReg(); } else { assert(MI->getOperand(0).isFI() && "Unknown operand type"); - const TargetFrameLowering *TFI = AP.TM.getFrameLowering(); + const TargetFrameLowering *TFI = + AP.TM.getSubtargetImpl()->getFrameLowering(); Offset += TFI->getFrameIndexReference(*AP.MF, MI->getOperand(0).getIndex(), Reg); Deref = true; @@ -686,7 +678,7 @@ static bool emitDebugValueComment(const MachineInstr *MI, AsmPrinter &AP) { } if (Deref) OS << '['; - OS << AP.TM.getRegisterInfo()->getName(Reg); + OS << AP.TM.getSubtargetImpl()->getRegisterInfo()->getName(Reg); } if (Deref) @@ -709,8 +701,8 @@ AsmPrinter::CFIMoveType AsmPrinter::needsCFIMoves() { } bool AsmPrinter::needsSEHMoves() { - return MAI->getExceptionHandlingType() == ExceptionHandling::WinEH && - MF->getFunction()->needsUnwindTableEntry(); + return MAI->getExceptionHandlingType() == ExceptionHandling::ItaniumWinEH && + MF->getFunction()->needsUnwindTableEntry(); } void AsmPrinter::emitCFIInstruction(const MachineInstr &MI) { @@ -722,9 +714,6 @@ void AsmPrinter::emitCFIInstruction(const MachineInstr &MI) { if (needsCFIMoves() == CFI_M_None) return; - if (MMI->getCompactUnwindEncoding() != 0) - OutStreamer.EmitCompactUnwindEncoding(MMI->getCompactUnwindEncoding()); - const MachineModuleInfo &MMI = MF->getMMI(); const std::vector<MCCFIInstruction> &Instrs = MMI.getFrameInstructions(); unsigned CFIIndex = MI.getOperand(0).getCFIIndex(); @@ -742,12 +731,10 @@ void AsmPrinter::EmitFunctionBody() { // Print out code for the function. bool HasAnyRealCode = false; - const MachineInstr *LastMI = nullptr; for (auto &MBB : *MF) { // Print a label for the basic block. EmitBasicBlockStart(MBB); for (auto &MI : MBB) { - LastMI = &MI; // Print the assembly for the instruction. if (!MI.isPosition() && !MI.isImplicitDef() && !MI.isKill() && @@ -804,26 +791,22 @@ void AsmPrinter::EmitFunctionBody() { } } } - } - // If the last instruction was a prolog label, then we have a situation where - // we emitted a prolog but no function body. This results in the ending prolog - // label equaling the end of function label and an invalid "row" in the - // FDE. We need to emit a noop in this situation so that the FDE's rows are - // valid. - bool RequiresNoop = LastMI && LastMI->isCFIInstruction(); + EmitBasicBlockEnd(MBB); + } // If the function is empty and the object file uses .subsections_via_symbols, // then we need to emit *something* to the function body to prevent the // labels from collapsing together. Just emit a noop. - if ((MAI->hasSubsectionsViaSymbols() && !HasAnyRealCode) || RequiresNoop) { + if ((MAI->hasSubsectionsViaSymbols() && !HasAnyRealCode)) { MCInst Noop; - TM.getInstrInfo()->getNoopForMachoTarget(Noop); - if (Noop.getOpcode()) { - OutStreamer.AddComment("avoids zero-length function"); + TM.getSubtargetImpl()->getInstrInfo()->getNoopForMachoTarget(Noop); + OutStreamer.AddComment("avoids zero-length function"); + + // Targets can opt-out of emitting the noop here by leaving the opcode + // unspecified. + if (Noop.getOpcode()) OutStreamer.EmitInstruction(Noop, getSubtargetInfo()); - } else // Target not mc-ized yet. - OutStreamer.EmitRawText(StringRef("\tnop\n")); } const Function *F = MF->getFunction(); @@ -895,17 +878,18 @@ bool AsmPrinter::doFinalization(Module &M) { unsigned Arch = Triple(getTargetTriple()).getArch(); bool IsThumb = (Arch == Triple::thumb || Arch == Triple::thumbeb); MCInst TrapInst; - TM.getInstrInfo()->getTrap(TrapInst); + TM.getSubtargetImpl()->getInstrInfo()->getTrap(TrapInst); + unsigned LogAlignment = llvm::Log2_64(JITI->entryByteAlignment()); + + // Emit the right section for these functions. + OutStreamer.SwitchSection(OutContext.getObjectFileInfo()->getTextSection()); for (const auto &KV : JITI->getTables()) { uint64_t Count = 0; for (const auto &FunPair : KV.second) { // Emit the function labels to make this be a function entry point. MCSymbol *FunSym = OutContext.GetOrCreateSymbol(FunPair.second->getName()); - OutStreamer.EmitSymbolAttribute(FunSym, MCSA_Global); - // FIXME: JumpTableInstrInfo should store information about the required - // alignment of table entries and the size of the padding instruction. - EmitAlignment(3); + EmitAlignment(LogAlignment); if (IsThumb) OutStreamer.EmitThumbFunc(FunSym); if (MAI->hasDotTypeDotSizeDirective()) @@ -920,16 +904,16 @@ bool AsmPrinter::doFinalization(Module &M) { const MCSymbolRefExpr *TargetSymRef = MCSymbolRefExpr::Create(TargetSymbol, MCSymbolRefExpr::VK_PLT, OutContext); - TM.getInstrInfo()->getUnconditionalBranch(JumpToFun, TargetSymRef); + TM.getSubtargetImpl()->getInstrInfo()->getUnconditionalBranch( + JumpToFun, TargetSymRef); OutStreamer.EmitInstruction(JumpToFun, getSubtargetInfo()); ++Count; } // Emit enough padding instructions to fill up to the next power of two. - // This assumes that the trap instruction takes 8 bytes or fewer. uint64_t Remaining = NextPowerOf2(Count) - Count; for (uint64_t C = 0; C < Remaining; ++C) { - EmitAlignment(3); + EmitAlignment(LogAlignment); OutStreamer.EmitInstruction(TrapInst, getSubtargetInfo()); } @@ -976,24 +960,21 @@ bool AsmPrinter::doFinalization(Module &M) { } } - if (MAI->hasSetDirective()) { - OutStreamer.AddBlankLine(); - for (const auto &Alias : M.aliases()) { - MCSymbol *Name = getSymbol(&Alias); + OutStreamer.AddBlankLine(); + for (const auto &Alias : M.aliases()) { + MCSymbol *Name = getSymbol(&Alias); - if (Alias.hasExternalLinkage() || !MAI->getWeakRefDirective()) - OutStreamer.EmitSymbolAttribute(Name, MCSA_Global); - else if (Alias.hasWeakLinkage() || Alias.hasLinkOnceLinkage()) - OutStreamer.EmitSymbolAttribute(Name, MCSA_WeakReference); - else - assert(Alias.hasLocalLinkage() && "Invalid alias linkage"); + if (Alias.hasExternalLinkage() || !MAI->getWeakRefDirective()) + OutStreamer.EmitSymbolAttribute(Name, MCSA_Global); + else if (Alias.hasWeakLinkage() || Alias.hasLinkOnceLinkage()) + OutStreamer.EmitSymbolAttribute(Name, MCSA_WeakReference); + else + assert(Alias.hasLocalLinkage() && "Invalid alias linkage"); - EmitVisibility(Name, Alias.getVisibility()); + EmitVisibility(Name, Alias.getVisibility()); - // Emit the directives as assignments aka .set: - OutStreamer.EmitAssignment(Name, - lowerConstant(Alias.getAliasee(), *this)); - } + // Emit the directives as assignments aka .set: + OutStreamer.EmitAssignment(Name, lowerConstant(Alias.getAliasee(), *this)); } GCModuleInfo *MI = getAnalysisIfAvailable<GCModuleInfo>(); @@ -1062,23 +1043,14 @@ void AsmPrinter::EmitConstantPool() { const MachineConstantPoolEntry &CPE = CP[i]; unsigned Align = CPE.getAlignment(); - SectionKind Kind; - switch (CPE.getRelocationInfo()) { - default: llvm_unreachable("Unknown section kind"); - case 2: Kind = SectionKind::getReadOnlyWithRel(); break; - case 1: - Kind = SectionKind::getReadOnlyWithRelLocal(); - break; - case 0: - switch (TM.getDataLayout()->getTypeAllocSize(CPE.getType())) { - case 4: Kind = SectionKind::getMergeableConst4(); break; - case 8: Kind = SectionKind::getMergeableConst8(); break; - case 16: Kind = SectionKind::getMergeableConst16();break; - default: Kind = SectionKind::getMergeableConst(); break; - } - } + SectionKind Kind = + CPE.getSectionKind(TM.getSubtargetImpl()->getDataLayout()); + + const Constant *C = nullptr; + if (!CPE.isMachineConstantPoolEntry()) + C = CPE.Val.ConstVal; - const MCSection *S = getObjFileLowering().getSectionForConstant(Kind); + const MCSection *S = getObjFileLowering().getSectionForConstant(Kind, C); // The number of sections are small, just do a linear search from the // last section to the first. @@ -1101,13 +1073,22 @@ void AsmPrinter::EmitConstantPool() { } // Now print stuff into the calculated sections. + const MCSection *CurSection = nullptr; + unsigned Offset = 0; for (unsigned i = 0, e = CPSections.size(); i != e; ++i) { - OutStreamer.SwitchSection(CPSections[i].S); - EmitAlignment(Log2_32(CPSections[i].Alignment)); - - unsigned Offset = 0; for (unsigned j = 0, ee = CPSections[i].CPEs.size(); j != ee; ++j) { unsigned CPI = CPSections[i].CPEs[j]; + MCSymbol *Sym = GetCPISymbol(CPI); + if (!Sym->isUndefined()) + continue; + + if (CurSection != CPSections[i].S) { + OutStreamer.SwitchSection(CPSections[i].S); + EmitAlignment(Log2_32(CPSections[i].Alignment)); + CurSection = CPSections[i].S; + Offset = 0; + } + MachineConstantPoolEntry CPE = CP[CPI]; // Emit inter-object padding for alignment. @@ -1116,9 +1097,10 @@ void AsmPrinter::EmitConstantPool() { OutStreamer.EmitZeros(NewOffset - Offset); Type *Ty = CPE.getType(); - Offset = NewOffset + TM.getDataLayout()->getTypeAllocSize(Ty); - OutStreamer.EmitLabel(GetCPISymbol(CPI)); + Offset = NewOffset + + TM.getSubtargetImpl()->getDataLayout()->getTypeAllocSize(Ty); + OutStreamer.EmitLabel(Sym); if (CPE.isMachineConstantPoolEntry()) EmitMachineConstantPoolValue(CPE.Val.MachineCPVal); else @@ -1131,7 +1113,7 @@ void AsmPrinter::EmitConstantPool() { /// by the current function to the current output stream. /// void AsmPrinter::EmitJumpTableInfo() { - const DataLayout *DL = MF->getTarget().getDataLayout(); + const DataLayout *DL = MF->getSubtarget().getDataLayout(); const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo(); if (!MJTI) return; if (MJTI->getEntryKind() == MachineJumpTableInfo::EK_Inline) return; @@ -1156,12 +1138,14 @@ void AsmPrinter::EmitJumpTableInfo() { } else { // Otherwise, drop it in the readonly section. const MCSection *ReadOnlySection = - getObjFileLowering().getSectionForConstant(SectionKind::getReadOnly()); + getObjFileLowering().getSectionForConstant(SectionKind::getReadOnly(), + /*C=*/nullptr); OutStreamer.SwitchSection(ReadOnlySection); JTInDiffSection = true; } - EmitAlignment(Log2_32(MJTI->getEntryAlignment(*TM.getDataLayout()))); + EmitAlignment(Log2_32( + MJTI->getEntryAlignment(*TM.getSubtargetImpl()->getDataLayout()))); // Jump tables in code sections are marked with a data_region directive // where that's supported. @@ -1174,17 +1158,17 @@ void AsmPrinter::EmitJumpTableInfo() { // If this jump table was deleted, ignore it. if (JTBBs.empty()) continue; - // For the EK_LabelDifference32 entry, if the target supports .set, emit a - // .set directive for each unique entry. This reduces the number of - // relocations the assembler will generate for the jump table. + // For the EK_LabelDifference32 entry, if using .set avoids a relocation, + /// emit a .set directive for each unique entry. if (MJTI->getEntryKind() == MachineJumpTableInfo::EK_LabelDifference32 && - MAI->hasSetDirective()) { + MAI->doesSetDirectiveSuppressesReloc()) { SmallPtrSet<const MachineBasicBlock*, 16> EmittedSets; - const TargetLowering *TLI = TM.getTargetLowering(); + const TargetLowering *TLI = TM.getSubtargetImpl()->getTargetLowering(); const MCExpr *Base = TLI->getPICJumpTableRelocBaseExpr(MF,JTI,OutContext); for (unsigned ii = 0, ee = JTBBs.size(); ii != ee; ++ii) { const MachineBasicBlock *MBB = JTBBs[ii]; - if (!EmittedSets.insert(MBB)) continue; + if (!EmittedSets.insert(MBB).second) + continue; // .set LJTSet, LBB32-base const MCExpr *LHS = @@ -1223,8 +1207,9 @@ void AsmPrinter::EmitJumpTableEntry(const MachineJumpTableInfo *MJTI, case MachineJumpTableInfo::EK_Inline: llvm_unreachable("Cannot emit EK_Inline jump table entry"); case MachineJumpTableInfo::EK_Custom32: - Value = TM.getTargetLowering()->LowerCustomJumpTableEntry(MJTI, MBB, UID, - OutContext); + Value = + TM.getSubtargetImpl()->getTargetLowering()->LowerCustomJumpTableEntry( + MJTI, MBB, UID, OutContext); break; case MachineJumpTableInfo::EK_BlockAddress: // EK_BlockAddress - Each entry is a plain address of block, e.g.: @@ -1250,34 +1235,30 @@ void AsmPrinter::EmitJumpTableEntry(const MachineJumpTableInfo *MJTI, } case MachineJumpTableInfo::EK_LabelDifference32: { - // EK_LabelDifference32 - Each entry is the address of the block minus - // the address of the jump table. This is used for PIC jump tables where - // gprel32 is not supported. e.g.: + // Each entry is the address of the block minus the address of the jump + // table. This is used for PIC jump tables where gprel32 is not supported. + // e.g.: // .word LBB123 - LJTI1_2 - // If the .set directive is supported, this is emitted as: + // If the .set directive avoids relocations, this is emitted as: // .set L4_5_set_123, LBB123 - LJTI1_2 // .word L4_5_set_123 - - // If we have emitted set directives for the jump table entries, print - // them rather than the entries themselves. If we're emitting PIC, then - // emit the table entries as differences between two text section labels. - if (MAI->hasSetDirective()) { - // If we used .set, reference the .set's symbol. + if (MAI->doesSetDirectiveSuppressesReloc()) { Value = MCSymbolRefExpr::Create(GetJTSetSymbol(UID, MBB->getNumber()), OutContext); break; } - // Otherwise, use the difference as the jump table entry. Value = MCSymbolRefExpr::Create(MBB->getSymbol(), OutContext); - const MCExpr *JTI = MCSymbolRefExpr::Create(GetJTISymbol(UID), OutContext); - Value = MCBinaryExpr::CreateSub(Value, JTI, OutContext); + const TargetLowering *TLI = TM.getSubtargetImpl()->getTargetLowering(); + const MCExpr *Base = TLI->getPICJumpTableRelocBaseExpr(MF, UID, OutContext); + Value = MCBinaryExpr::CreateSub(Value, Base, OutContext); break; } } assert(Value && "Unknown entry kind!"); - unsigned EntrySize = MJTI->getEntrySize(*TM.getDataLayout()); + unsigned EntrySize = + MJTI->getEntrySize(*TM.getSubtargetImpl()->getDataLayout()); OutStreamer.EmitValue(Value, EntrySize); } @@ -1387,7 +1368,7 @@ void AsmPrinter::EmitXXStructorList(const Constant *List, bool isCtor) { } // Emit the function pointers in the target-specific order - const DataLayout *DL = TM.getDataLayout(); + const DataLayout *DL = TM.getSubtargetImpl()->getDataLayout(); unsigned Align = Log2_32(DL->getPointerPrefAlignment()); std::stable_sort(Structors.begin(), Structors.end(), [](const Structor &L, @@ -1450,9 +1431,9 @@ void AsmPrinter::EmitInt32(int Value) const { OutStreamer.EmitIntValue(Value, 4); } -/// EmitLabelDifference - Emit something like ".long Hi-Lo" where the size -/// in bytes of the directive is specified by Size and Hi/Lo specify the -/// labels. This implicitly uses .set if it is available. +/// Emit something like ".long Hi-Lo" where the size in bytes of the directive +/// is specified by Size and Hi/Lo specify the labels. This implicitly uses +/// .set if it avoids relocations. void AsmPrinter::EmitLabelDifference(const MCSymbol *Hi, const MCSymbol *Lo, unsigned Size) const { // Get the Hi-Lo expression. @@ -1461,7 +1442,7 @@ void AsmPrinter::EmitLabelDifference(const MCSymbol *Hi, const MCSymbol *Lo, MCSymbolRefExpr::Create(Lo, OutContext), OutContext); - if (!MAI->hasSetDirective()) { + if (!MAI->doesSetDirectiveSuppressesReloc()) { OutStreamer.EmitValue(Diff, Size); return; } @@ -1472,36 +1453,6 @@ void AsmPrinter::EmitLabelDifference(const MCSymbol *Hi, const MCSymbol *Lo, OutStreamer.EmitSymbolValue(SetLabel, Size); } -/// EmitLabelOffsetDifference - Emit something like ".long Hi+Offset-Lo" -/// where the size in bytes of the directive is specified by Size and Hi/Lo -/// specify the labels. This implicitly uses .set if it is available. -void AsmPrinter::EmitLabelOffsetDifference(const MCSymbol *Hi, uint64_t Offset, - const MCSymbol *Lo, - unsigned Size) const { - - // Emit Hi+Offset - Lo - // Get the Hi+Offset expression. - const MCExpr *Plus = - MCBinaryExpr::CreateAdd(MCSymbolRefExpr::Create(Hi, OutContext), - MCConstantExpr::Create(Offset, OutContext), - OutContext); - - // Get the Hi+Offset-Lo expression. - const MCExpr *Diff = - MCBinaryExpr::CreateSub(Plus, - MCSymbolRefExpr::Create(Lo, OutContext), - OutContext); - - if (!MAI->hasSetDirective()) - OutStreamer.EmitValue(Diff, Size); - else { - // Otherwise, emit with .set (aka assignment). - MCSymbol *SetLabel = GetTempSymbol("set", SetCounter++); - OutStreamer.EmitAssignment(SetLabel, Diff); - OutStreamer.EmitSymbolValue(SetLabel, Size); - } -} - /// EmitLabelPlusOffset - Emit something like ".long Label+Offset" /// where the size in bytes of the directive is specified by Size and Label /// specifies the label. This implicitly uses .set if it is available. @@ -1531,7 +1482,9 @@ void AsmPrinter::EmitLabelPlusOffset(const MCSymbol *Label, uint64_t Offset, // if required for correctness. // void AsmPrinter::EmitAlignment(unsigned NumBits, const GlobalObject *GV) const { - if (GV) NumBits = getGVAlignmentLog2(GV, *TM.getDataLayout(), NumBits); + if (GV) + NumBits = getGVAlignmentLog2(GV, *TM.getSubtargetImpl()->getDataLayout(), + NumBits); if (NumBits == 0) return; // 1-byte aligned: no need to emit alignment. @@ -1577,8 +1530,8 @@ static const MCExpr *lowerConstant(const Constant *CV, AsmPrinter &AP) { // If the code isn't optimized, there may be outstanding folding // opportunities. Attempt to fold the expression using DataLayout as a // last resort before giving up. - if (Constant *C = - ConstantFoldConstantExpression(CE, AP.TM.getDataLayout())) + if (Constant *C = ConstantFoldConstantExpression( + CE, AP.TM.getSubtargetImpl()->getDataLayout())) if (C != CE) return lowerConstant(C, AP); @@ -1592,7 +1545,7 @@ static const MCExpr *lowerConstant(const Constant *CV, AsmPrinter &AP) { report_fatal_error(OS.str()); } case Instruction::GetElementPtr: { - const DataLayout &DL = *AP.TM.getDataLayout(); + const DataLayout &DL = *AP.TM.getSubtargetImpl()->getDataLayout(); // Generate a symbolic expression for the byte address APInt OffsetAI(DL.getPointerTypeSizeInBits(CE->getType()), 0); cast<GEPOperator>(CE)->accumulateConstantOffset(DL, OffsetAI); @@ -1616,7 +1569,7 @@ static const MCExpr *lowerConstant(const Constant *CV, AsmPrinter &AP) { return lowerConstant(CE->getOperand(0), AP); case Instruction::IntToPtr: { - const DataLayout &DL = *AP.TM.getDataLayout(); + const DataLayout &DL = *AP.TM.getSubtargetImpl()->getDataLayout(); // Handle casts to pointers by changing them into casts to the appropriate // integer type. This promotes constant folding and simplifies this code. Constant *Op = CE->getOperand(0); @@ -1626,7 +1579,7 @@ static const MCExpr *lowerConstant(const Constant *CV, AsmPrinter &AP) { } case Instruction::PtrToInt: { - const DataLayout &DL = *AP.TM.getDataLayout(); + const DataLayout &DL = *AP.TM.getSubtargetImpl()->getDataLayout(); // Support only foldable casts to/from pointers that can be eliminated by // changing the pointer to the appropriately sized integer type. Constant *Op = CE->getOperand(0); @@ -1699,7 +1652,8 @@ static int isRepeatedByteSequence(const Value *V, TargetMachine &TM) { if (const ConstantInt *CI = dyn_cast<ConstantInt>(V)) { if (CI->getBitWidth() > 64) return -1; - uint64_t Size = TM.getDataLayout()->getTypeAllocSize(V->getType()); + uint64_t Size = + TM.getSubtargetImpl()->getDataLayout()->getTypeAllocSize(V->getType()); uint64_t Value = CI->getZExtValue(); // Make sure the constant is at least 8 bits long and has a power @@ -1743,7 +1697,9 @@ static void emitGlobalConstantDataSequential(const ConstantDataSequential *CDS, // See if we can aggregate this into a .fill, if so, emit it as such. int Value = isRepeatedByteSequence(CDS, AP.TM); if (Value != -1) { - uint64_t Bytes = AP.TM.getDataLayout()->getTypeAllocSize(CDS->getType()); + uint64_t Bytes = + AP.TM.getSubtargetImpl()->getDataLayout()->getTypeAllocSize( + CDS->getType()); // Don't emit a 1-byte object as a .fill. if (Bytes > 1) return AP.OutStreamer.EmitFill(Bytes, Value); @@ -1793,7 +1749,7 @@ static void emitGlobalConstantDataSequential(const ConstantDataSequential *CDS, } } - const DataLayout &DL = *AP.TM.getDataLayout(); + const DataLayout &DL = *AP.TM.getSubtargetImpl()->getDataLayout(); unsigned Size = DL.getTypeAllocSize(CDS->getType()); unsigned EmittedSize = DL.getTypeAllocSize(CDS->getType()->getElementType()) * CDS->getNumElements(); @@ -1808,7 +1764,9 @@ static void emitGlobalConstantArray(const ConstantArray *CA, AsmPrinter &AP) { int Value = isRepeatedByteSequence(CA, AP.TM); if (Value != -1) { - uint64_t Bytes = AP.TM.getDataLayout()->getTypeAllocSize(CA->getType()); + uint64_t Bytes = + AP.TM.getSubtargetImpl()->getDataLayout()->getTypeAllocSize( + CA->getType()); AP.OutStreamer.EmitFill(Bytes, Value); } else { @@ -1821,7 +1779,7 @@ static void emitGlobalConstantVector(const ConstantVector *CV, AsmPrinter &AP) { for (unsigned i = 0, e = CV->getType()->getNumElements(); i != e; ++i) emitGlobalConstantImpl(CV->getOperand(i), AP); - const DataLayout &DL = *AP.TM.getDataLayout(); + const DataLayout &DL = *AP.TM.getSubtargetImpl()->getDataLayout(); unsigned Size = DL.getTypeAllocSize(CV->getType()); unsigned EmittedSize = DL.getTypeAllocSize(CV->getType()->getElementType()) * CV->getType()->getNumElements(); @@ -1831,7 +1789,7 @@ static void emitGlobalConstantVector(const ConstantVector *CV, AsmPrinter &AP) { static void emitGlobalConstantStruct(const ConstantStruct *CS, AsmPrinter &AP) { // Print the fields in successive locations. Pad to align if needed! - const DataLayout *DL = AP.TM.getDataLayout(); + const DataLayout *DL = AP.TM.getSubtargetImpl()->getDataLayout(); unsigned Size = DL->getTypeAllocSize(CS->getType()); const StructLayout *Layout = DL->getStructLayout(CS->getType()); uint64_t SizeSoFar = 0; @@ -1881,7 +1839,7 @@ static void emitGlobalConstantFP(const ConstantFP *CFP, AsmPrinter &AP) { // PPC's long double has odd notions of endianness compared to how LLVM // handles it: p[0] goes first for *big* endian on PPC. - if (AP.TM.getDataLayout()->isBigEndian() && + if (AP.TM.getSubtargetImpl()->getDataLayout()->isBigEndian() && !CFP->getType()->isPPC_FP128Ty()) { int Chunk = API.getNumWords() - 1; @@ -1900,13 +1858,13 @@ static void emitGlobalConstantFP(const ConstantFP *CFP, AsmPrinter &AP) { } // Emit the tail padding for the long double. - const DataLayout &DL = *AP.TM.getDataLayout(); + const DataLayout &DL = *AP.TM.getSubtargetImpl()->getDataLayout(); AP.OutStreamer.EmitZeros(DL.getTypeAllocSize(CFP->getType()) - DL.getTypeStoreSize(CFP->getType())); } static void emitGlobalConstantLargeInt(const ConstantInt *CI, AsmPrinter &AP) { - const DataLayout *DL = AP.TM.getDataLayout(); + const DataLayout *DL = AP.TM.getSubtargetImpl()->getDataLayout(); unsigned BitWidth = CI->getBitWidth(); // Copy the value as we may massage the layout for constants whose bit width @@ -1952,7 +1910,8 @@ static void emitGlobalConstantLargeInt(const ConstantInt *CI, AsmPrinter &AP) { // Emit the extra bits after the 64-bits chunks. // Emit a directive that fills the expected size. - uint64_t Size = AP.TM.getDataLayout()->getTypeAllocSize(CI->getType()); + uint64_t Size = AP.TM.getSubtargetImpl()->getDataLayout()->getTypeAllocSize( + CI->getType()); Size -= (BitWidth / 64) * 8; assert(Size && Size * 8 >= ExtraBitsSize && (ExtraBits & (((uint64_t)-1) >> (64 - ExtraBitsSize))) @@ -1962,7 +1921,7 @@ static void emitGlobalConstantLargeInt(const ConstantInt *CI, AsmPrinter &AP) { } static void emitGlobalConstantImpl(const Constant *CV, AsmPrinter &AP) { - const DataLayout *DL = AP.TM.getDataLayout(); + const DataLayout *DL = AP.TM.getSubtargetImpl()->getDataLayout(); uint64_t Size = DL->getTypeAllocSize(CV->getType()); if (isa<ConstantAggregateZero>(CV) || isa<UndefValue>(CV)) return AP.OutStreamer.EmitZeros(Size); @@ -2027,7 +1986,8 @@ static void emitGlobalConstantImpl(const Constant *CV, AsmPrinter &AP) { /// EmitGlobalConstant - Print a general LLVM constant to the .s file. void AsmPrinter::EmitGlobalConstant(const Constant *CV) { - uint64_t Size = TM.getDataLayout()->getTypeAllocSize(CV->getType()); + uint64_t Size = + TM.getSubtargetImpl()->getDataLayout()->getTypeAllocSize(CV->getType()); if (Size) emitGlobalConstantImpl(CV, *this); else if (MAI->hasSubsectionsViaSymbols()) { @@ -2056,7 +2016,7 @@ void AsmPrinter::printOffset(int64_t Offset, raw_ostream &OS) const { /// GetTempSymbol - Return the MCSymbol corresponding to the assembler /// temporary label with the specified stem and unique ID. MCSymbol *AsmPrinter::GetTempSymbol(Twine Name, unsigned ID) const { - const DataLayout *DL = TM.getDataLayout(); + const DataLayout *DL = TM.getSubtargetImpl()->getDataLayout(); return OutContext.GetOrCreateSymbol(Twine(DL->getPrivateGlobalPrefix()) + Name + Twine(ID)); } @@ -2064,7 +2024,7 @@ MCSymbol *AsmPrinter::GetTempSymbol(Twine Name, unsigned ID) const { /// GetTempSymbol - Return an assembler temporary label with the specified /// stem. MCSymbol *AsmPrinter::GetTempSymbol(Twine Name) const { - const DataLayout *DL = TM.getDataLayout(); + const DataLayout *DL = TM.getSubtargetImpl()->getDataLayout(); return OutContext.GetOrCreateSymbol(Twine(DL->getPrivateGlobalPrefix())+ Name); } @@ -2080,7 +2040,7 @@ MCSymbol *AsmPrinter::GetBlockAddressSymbol(const BasicBlock *BB) const { /// GetCPISymbol - Return the symbol for the specified constant pool entry. MCSymbol *AsmPrinter::GetCPISymbol(unsigned CPID) const { - const DataLayout *DL = TM.getDataLayout(); + const DataLayout *DL = TM.getSubtargetImpl()->getDataLayout(); return OutContext.GetOrCreateSymbol (Twine(DL->getPrivateGlobalPrefix()) + "CPI" + Twine(getFunctionNumber()) + "_" + Twine(CPID)); @@ -2094,7 +2054,7 @@ MCSymbol *AsmPrinter::GetJTISymbol(unsigned JTID, bool isLinkerPrivate) const { /// GetJTSetSymbol - Return the symbol for the specified jump table .set /// FIXME: privatize to AsmPrinter. MCSymbol *AsmPrinter::GetJTSetSymbol(unsigned UID, unsigned MBBID) const { - const DataLayout *DL = TM.getDataLayout(); + const DataLayout *DL = TM.getSubtargetImpl()->getDataLayout(); return OutContext.GetOrCreateSymbol (Twine(DL->getPrivateGlobalPrefix()) + Twine(getFunctionNumber()) + "_" + Twine(UID) + "_set_" + Twine(MBBID)); diff --git a/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp b/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp index 02cd12b..05f6a68 100644 --- a/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp +++ b/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp @@ -27,6 +27,7 @@ #include "llvm/Target/TargetLoweringObjectFile.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Target/TargetSubtargetInfo.h" using namespace llvm; #define DEBUG_TYPE "asm-printer" @@ -130,7 +131,7 @@ unsigned AsmPrinter::GetSizeOfEncodedValue(unsigned Encoding) const { default: llvm_unreachable("Invalid encoded value."); case dwarf::DW_EH_PE_absptr: - return TM.getDataLayout()->getPointerSize(); + return TM.getSubtargetImpl()->getDataLayout()->getPointerSize(); case dwarf::DW_EH_PE_udata2: return 2; case dwarf::DW_EH_PE_udata4: @@ -214,13 +215,10 @@ static void emitDwarfRegOpIndirect(ByteStreamer &Streamer, int Reg, int Offset, Streamer.EmitInt8(dwarf::DW_OP_deref, "DW_OP_deref"); } -/// Emit a dwarf register operation for describing -/// - a small value occupying only part of a register or -/// - a small register representing only part of a value. -static void emitDwarfOpPiece(ByteStreamer &Streamer, unsigned SizeInBits, - unsigned OffsetInBits) { - assert(SizeInBits > 0 && "zero-sized piece"); - unsigned SizeOfByte = 8; +void AsmPrinter::EmitDwarfOpPiece(ByteStreamer &Streamer, unsigned SizeInBits, + unsigned OffsetInBits) const { + assert(SizeInBits > 0 && "piece has size zero"); + const unsigned SizeOfByte = 8; if (OffsetInBits > 0 || SizeInBits % SizeOfByte) { Streamer.EmitInt8(dwarf::DW_OP_bit_piece, "DW_OP_bit_piece"); Streamer.EmitULEB128(SizeInBits, Twine(SizeInBits)); @@ -249,13 +247,13 @@ void AsmPrinter::EmitDwarfRegOpPiece(ByteStreamer &Streamer, unsigned PieceSizeInBits, unsigned PieceOffsetInBits) const { assert(MLoc.isReg() && "MLoc must be a register"); - const TargetRegisterInfo *TRI = TM.getRegisterInfo(); + const TargetRegisterInfo *TRI = TM.getSubtargetImpl()->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); + EmitDwarfOpPiece(Streamer, PieceSizeInBits, PieceOffsetInBits); return; } @@ -266,19 +264,19 @@ void AsmPrinter::EmitDwarfRegOpPiece(ByteStreamer &Streamer, if (Reg >= 0) { unsigned Idx = TRI->getSubRegIndex(*SR, MLoc.getReg()); unsigned Size = TRI->getSubRegIdxSize(Idx); - unsigned Offset = TRI->getSubRegIdxOffset(Idx); + unsigned RegOffset = TRI->getSubRegIdxOffset(Idx); OutStreamer.AddComment("super-register"); emitDwarfRegOp(Streamer, Reg); - if (PieceOffsetInBits == Offset) { - emitDwarfOpPiece(Streamer, Size, Offset); + if (PieceOffsetInBits == RegOffset) { + EmitDwarfOpPiece(Streamer, Size, RegOffset); } 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); + if (RegOffset) + emitDwarfOpShr(Streamer, RegOffset); + EmitDwarfOpPiece(Streamer, Size, PieceOffsetInBits); } return; } @@ -312,7 +310,7 @@ void AsmPrinter::EmitDwarfRegOpPiece(ByteStreamer &Streamer, if (Reg >= 0 && Intersection.any()) { OutStreamer.AddComment("sub-register"); emitDwarfRegOp(Streamer, Reg); - emitDwarfOpPiece(Streamer, Size, Offset == CurPos ? 0 : Offset); + EmitDwarfOpPiece(Streamer, Size, Offset == CurPos ? 0 : Offset); CurPos = Offset + Size; // Mark it as emitted. @@ -331,7 +329,7 @@ void AsmPrinter::EmitDwarfRegOpPiece(ByteStreamer &Streamer, void AsmPrinter::EmitDwarfRegOp(ByteStreamer &Streamer, const MachineLocation &MLoc, bool Indirect) const { - const TargetRegisterInfo *TRI = TM.getRegisterInfo(); + const TargetRegisterInfo *TRI = TM.getSubtargetImpl()->getRegisterInfo(); int Reg = TRI->getDwarfRegNum(MLoc.getReg(), false); if (Reg < 0) { // We assume that pointers are always in an addressable register. diff --git a/lib/CodeGen/AsmPrinter/AsmPrinterHandler.h b/lib/CodeGen/AsmPrinter/AsmPrinterHandler.h index 2825367..31867dd 100644 --- a/lib/CodeGen/AsmPrinter/AsmPrinterHandler.h +++ b/lib/CodeGen/AsmPrinter/AsmPrinterHandler.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef CODEGEN_ASMPRINTER_ASMPRINTERHANDLER_H__ -#define CODEGEN_ASMPRINTER_ASMPRINTERHANDLER_H__ +#ifndef LLVM_LIB_CODEGEN_ASMPRINTER_ASMPRINTERHANDLER_H +#define LLVM_LIB_CODEGEN_ASMPRINTER_ASMPRINTERHANDLER_H #include "llvm/Support/DataTypes.h" diff --git a/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp b/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp index 46ee0c8..cca5f22 100644 --- a/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp +++ b/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp @@ -33,6 +33,7 @@ #include "llvm/Support/TargetRegistry.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetRegisterInfo.h" #include "llvm/Target/TargetSubtargetInfo.h" using namespace llvm; @@ -110,14 +111,14 @@ void AsmPrinter::EmitInlineAsm(StringRef Str, const MDNode *LocMDNode, HasDiagHandler = true; } - MemoryBuffer *Buffer; + std::unique_ptr<MemoryBuffer> Buffer; if (isNullTerminated) Buffer = MemoryBuffer::getMemBuffer(Str, "<inline asm>"); else Buffer = MemoryBuffer::getMemBufferCopy(Str, "<inline asm>"); // Tell SrcMgr about this buffer, it takes ownership of the buffer. - SrcMgr.AddNewSourceBuffer(Buffer, SMLoc()); + SrcMgr.AddNewSourceBuffer(std::move(Buffer), SMLoc()); std::unique_ptr<MCAsmParser> Parser( createMCAsmParser(SrcMgr, OutContext, OutStreamer, *MAI)); @@ -146,6 +147,10 @@ void AsmPrinter::EmitInlineAsm(StringRef Str, const MDNode *LocMDNode, " we don't have an asm parser for this target\n"); Parser->setAssemblerDialect(Dialect); Parser->setTargetParser(*TAP.get()); + if (MF) { + const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo(); + TAP->SetFrameRegister(TRI->getFrameRegister(*MF)); + } // Don't implicitly switch to the text section before the asm. int Res = Parser->Run(/*NoInitialTextSection*/ true, @@ -500,7 +505,7 @@ void AsmPrinter::EmitInlineAsm(const MachineInstr *MI) const { /// for their own strange codes. void AsmPrinter::PrintSpecial(const MachineInstr *MI, raw_ostream &OS, const char *Code) const { - const DataLayout *DL = TM.getDataLayout(); + const DataLayout *DL = TM.getSubtargetImpl()->getDataLayout(); if (!strcmp(Code, "private")) { OS << DL->getPrivateGlobalPrefix(); } else if (!strcmp(Code, "comment")) { diff --git a/lib/CodeGen/AsmPrinter/ByteStreamer.h b/lib/CodeGen/AsmPrinter/ByteStreamer.h index 6c01d65..0cc8353 100644 --- a/lib/CodeGen/AsmPrinter/ByteStreamer.h +++ b/lib/CodeGen/AsmPrinter/ByteStreamer.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CODEGEN_BYTESTREAMER_H -#define LLVM_CODEGEN_BYTESTREAMER_H +#ifndef LLVM_LIB_CODEGEN_ASMPRINTER_BYTESTREAMER_H +#define LLVM_LIB_CODEGEN_ASMPRINTER_BYTESTREAMER_H #include "llvm/ADT/ArrayRef.h" #include "llvm/CodeGen/AsmPrinter.h" diff --git a/lib/CodeGen/AsmPrinter/CMakeLists.txt b/lib/CodeGen/AsmPrinter/CMakeLists.txt index f555f21..e6b7d64 100644 --- a/lib/CodeGen/AsmPrinter/CMakeLists.txt +++ b/lib/CodeGen/AsmPrinter/CMakeLists.txt @@ -9,6 +9,7 @@ add_llvm_library(LLVMAsmPrinter DIEHash.cpp DwarfAccelTable.cpp DwarfCFIException.cpp + DwarfCompileUnit.cpp DwarfDebug.cpp DwarfFile.cpp DwarfStringPool.cpp diff --git a/lib/CodeGen/AsmPrinter/DIE.cpp b/lib/CodeGen/AsmPrinter/DIE.cpp index c3dcd9c..50ea369 100644 --- a/lib/CodeGen/AsmPrinter/DIE.cpp +++ b/lib/CodeGen/AsmPrinter/DIE.cpp @@ -12,12 +12,15 @@ //===----------------------------------------------------------------------===// #include "DIE.h" + +#include "DwarfCompileUnit.h" #include "DwarfDebug.h" #include "DwarfUnit.h" #include "llvm/ADT/Twine.h" #include "llvm/CodeGen/AsmPrinter.h" #include "llvm/IR/DataLayout.h" #include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCContext.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSymbol.h" #include "llvm/Support/Debug.h" @@ -370,6 +373,29 @@ void DIEString::print(raw_ostream &O) const { // DIEEntry Implementation //===----------------------------------------------------------------------===// +/// Emit something like ".long Hi+Offset-Lo" where the size in bytes of the +/// directive is specified by Size and Hi/Lo specify the labels. +static void emitLabelOffsetDifference(MCStreamer &Streamer, const MCSymbol *Hi, + uint64_t Offset, const MCSymbol *Lo, + unsigned Size) { + MCContext &Context = Streamer.getContext(); + + // Emit Hi+Offset - Lo + // Get the Hi+Offset expression. + const MCExpr *Plus = + MCBinaryExpr::CreateAdd(MCSymbolRefExpr::Create(Hi, Context), + MCConstantExpr::Create(Offset, Context), Context); + + // Get the Hi+Offset-Lo expression. + const MCExpr *Diff = MCBinaryExpr::CreateSub( + Plus, MCSymbolRefExpr::Create(Lo, Context), Context); + + // Otherwise, emit with .set (aka assignment). + MCSymbol *SetLabel = Context.CreateTempSymbol(); + Streamer.EmitAssignment(SetLabel, Diff); + Streamer.EmitSymbolValue(SetLabel, Size); +} + /// EmitValue - Emit debug information entry offset. /// void DIEEntry::EmitValue(AsmPrinter *AP, dwarf::Form Form) const { @@ -388,9 +414,9 @@ void DIEEntry::EmitValue(AsmPrinter *AP, dwarf::Form Form) const { AP->EmitLabelPlusOffset(CU->getSectionSym(), Addr, DIEEntry::getRefAddrSize(AP)); else - AP->EmitLabelOffsetDifference(CU->getSectionSym(), Addr, - CU->getSectionSym(), - DIEEntry::getRefAddrSize(AP)); + emitLabelOffsetDifference(AP->OutStreamer, CU->getSectionSym(), Addr, + CU->getSectionSym(), + DIEEntry::getRefAddrSize(AP)); } else AP->EmitInt32(Entry.getOffset()); } diff --git a/lib/CodeGen/AsmPrinter/DIE.h b/lib/CodeGen/AsmPrinter/DIE.h index ef05f17..e310aef 100644 --- a/lib/CodeGen/AsmPrinter/DIE.h +++ b/lib/CodeGen/AsmPrinter/DIE.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef CODEGEN_ASMPRINTER_DIE_H__ -#define CODEGEN_ASMPRINTER_DIE_H__ +#ifndef LLVM_LIB_CODEGEN_ASMPRINTER_DIE_H +#define LLVM_LIB_CODEGEN_ASMPRINTER_DIE_H #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/SmallVector.h" @@ -381,10 +381,10 @@ public: /// class DIEString : public DIEValue { const DIEValue *Access; - const StringRef Str; + StringRef Str; public: - DIEString(const DIEValue *Acc, const StringRef S) + DIEString(const DIEValue *Acc, StringRef S) : DIEValue(isString), Access(Acc), Str(S) {} /// getString - Grab the string out of the object. diff --git a/lib/CodeGen/AsmPrinter/DIEHash.cpp b/lib/CodeGen/AsmPrinter/DIEHash.cpp index c2fad59..b2a3ba8 100644 --- a/lib/CodeGen/AsmPrinter/DIEHash.cpp +++ b/lib/CodeGen/AsmPrinter/DIEHash.cpp @@ -261,7 +261,7 @@ void DIEHash::hashDIEEntry(dwarf::Attribute Attribute, dwarf::Tag Tag, return; } - // otherwise, b) use the letter 'T' as a the marker, ... + // otherwise, b) use the letter 'T' as the marker, ... addULEB128('T'); addULEB128(Attribute); diff --git a/lib/CodeGen/AsmPrinter/DIEHash.h b/lib/CodeGen/AsmPrinter/DIEHash.h index 175d660..872aa0e 100644 --- a/lib/CodeGen/AsmPrinter/DIEHash.h +++ b/lib/CodeGen/AsmPrinter/DIEHash.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef CODEGEN_ASMPRINTER_DIEHASH_H__ -#define CODEGEN_ASMPRINTER_DIEHASH_H__ +#ifndef LLVM_LIB_CODEGEN_ASMPRINTER_DIEHASH_H +#define LLVM_LIB_CODEGEN_ASMPRINTER_DIEHASH_H #include "DIE.h" #include "llvm/ADT/DenseMap.h" diff --git a/lib/CodeGen/AsmPrinter/DbgValueHistoryCalculator.cpp b/lib/CodeGen/AsmPrinter/DbgValueHistoryCalculator.cpp index a66d08e..0c2a5e5 100644 --- a/lib/CodeGen/AsmPrinter/DbgValueHistoryCalculator.cpp +++ b/lib/CodeGen/AsmPrinter/DbgValueHistoryCalculator.cpp @@ -8,25 +8,25 @@ //===----------------------------------------------------------------------===// #include "DbgValueHistoryCalculator.h" +#include "llvm/ADT/BitVector.h" #include "llvm/ADT/SmallVector.h" #include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/CodeGen/MachineFunction.h" +#include "llvm/IR/DebugInfo.h" #include "llvm/Support/Debug.h" #include "llvm/Target/TargetRegisterInfo.h" #include <algorithm> #include <map> -#include <set> +using namespace llvm; #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); + assert(MI.getNumOperands() == 4); // 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; @@ -36,7 +36,7 @@ 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); + assert(MI.isDebugValue() && "not a DBG_VALUE"); auto &Ranges = VarInstrRanges[Var]; if (!Ranges.empty() && Ranges.back().second == nullptr && Ranges.back().first->isIdenticalTo(&MI)) { @@ -96,6 +96,19 @@ static void addRegDescribedVar(RegDescribedVarsMap &RegVars, VarSet.push_back(Var); } +// \brief Terminate the location range for variables described by register at +// @I by inserting @ClobberingInstr to their history. +static void clobberRegisterUses(RegDescribedVarsMap &RegVars, + RegDescribedVarsMap::iterator I, + DbgValueHistoryMap &HistMap, + const MachineInstr &ClobberingInstr) { + // Iterate over all variables described by this register and add this + // instruction to their history, clobbering it. + for (const auto &Var : I->second) + HistMap.endInstrRange(Var, ClobberingInstr); + RegVars.erase(I); +} + // \brief Terminate the location range for variables described by register // @RegNo by inserting @ClobberingInstr to their history. static void clobberRegisterUses(RegDescribedVarsMap &RegVars, unsigned RegNo, @@ -104,22 +117,26 @@ static void clobberRegisterUses(RegDescribedVarsMap &RegVars, unsigned RegNo, 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); + clobberRegisterUses(RegVars, I, HistMap, ClobberingInstr); } -// \brief Collect all registers clobbered by @MI and insert them to @Regs. -static void collectClobberedRegisters(const MachineInstr &MI, +// \brief Collect all registers clobbered by @MI and apply the functor +// @Func to their RegNo. +// @Func should be a functor with a void(unsigned) signature. We're +// not using std::function here for performance reasons. It has a +// small but measurable impact. By using a functor instead of a +// std::set& here, we can avoid the overhead of constructing +// temporaries in calculateDbgValueHistory, which has a significant +// performance impact. +template<typename Callable> +static void applyToClobberedRegisters(const MachineInstr &MI, const TargetRegisterInfo *TRI, - std::set<unsigned> &Regs) { + Callable Func) { for (const MachineOperand &MO : MI.operands()) { if (!MO.isReg() || !MO.isDef() || !MO.getReg()) continue; for (MCRegAliasIterator AI(MO.getReg(), TRI, true); AI.isValid(); ++AI) - Regs.insert(*AI); + Func(*AI); } } @@ -133,11 +150,12 @@ static const MachineInstr *getFirstEpilogueInst(const MachineBasicBlock &MBB) { // as the return instruction. DebugLoc LastLoc = LastMI->getDebugLoc(); auto Res = LastMI; - for (MachineBasicBlock::const_reverse_iterator I(std::next(LastMI)); I != MBB.rend(); - ++I) { + for (MachineBasicBlock::const_reverse_iterator I(std::next(LastMI)), + E = MBB.rend(); + I != E; ++I) { if (I->getDebugLoc() != LastLoc) return Res; - Res = std::prev(I.base()); + Res = &*I; } // If all instructions have the same debug location, assume whole MBB is // an epilogue. @@ -145,25 +163,26 @@ static const MachineInstr *getFirstEpilogueInst(const MachineBasicBlock &MBB) { } // \brief Collect registers that are modified in the function body (their -// contents is changed only in the prologue and epilogue). +// contents is changed outside of the prologue and epilogue). static void collectChangingRegs(const MachineFunction *MF, const TargetRegisterInfo *TRI, - std::set<unsigned> &Regs) { + BitVector &Regs) { for (const auto &MBB : *MF) { auto FirstEpilogueInst = getFirstEpilogueInst(MBB); - bool IsInEpilogue = false; + for (const auto &MI : MBB) { - IsInEpilogue |= &MI == FirstEpilogueInst; - if (!MI.getFlag(MachineInstr::FrameSetup) && !IsInEpilogue) - collectClobberedRegisters(MI, TRI, Regs); + if (&MI == FirstEpilogueInst) + break; + if (!MI.getFlag(MachineInstr::FrameSetup)) + applyToClobberedRegisters(MI, TRI, [&](unsigned r) { Regs.set(r); }); } } } -void calculateDbgValueHistory(const MachineFunction *MF, - const TargetRegisterInfo *TRI, - DbgValueHistoryMap &Result) { - std::set<unsigned> ChangingRegs; +void llvm::calculateDbgValueHistory(const MachineFunction *MF, + const TargetRegisterInfo *TRI, + DbgValueHistoryMap &Result) { + BitVector ChangingRegs(TRI->getNumRegs()); collectChangingRegs(MF, TRI, ChangingRegs); RegDescribedVarsMap RegVars; @@ -172,17 +191,18 @@ void calculateDbgValueHistory(const MachineFunction *MF, if (!MI.isDebugValue()) { // Not a DBG_VALUE instruction. It may clobber registers which describe // some variables. - std::set<unsigned> MIClobberedRegs; - collectClobberedRegisters(MI, TRI, MIClobberedRegs); - for (unsigned RegNo : MIClobberedRegs) { - if (ChangingRegs.count(RegNo)) + applyToClobberedRegisters(MI, TRI, [&](unsigned RegNo) { + if (ChangingRegs.test(RegNo)) clobberRegisterUses(RegVars, RegNo, Result, MI); - } + }); continue; } assert(MI.getNumOperands() > 1 && "Invalid DBG_VALUE instruction!"); - const MDNode *Var = MI.getDebugVariable(); + // Use the base variable (without any DW_OP_piece expressions) + // as index into History. The full variables including the + // piece expressions are attached to the MI. + DIVariable Var = MI.getDebugVariable(); if (unsigned PrevReg = Result.getRegisterForVar(Var)) dropRegDescribedVar(RegVars, PrevReg, Var); @@ -196,11 +216,12 @@ void calculateDbgValueHistory(const MachineFunction *MF, // 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()) { - for (unsigned RegNo : ChangingRegs) - clobberRegisterUses(RegVars, RegNo, Result, MBB.back()); + if (!MBB.empty() && &MBB != &MF->back()) { + for (auto I = RegVars.begin(), E = RegVars.end(); I != E;) { + auto CurElem = I++; // CurElem can be erased below. + if (ChangingRegs.test(CurElem->first)) + clobberRegisterUses(RegVars, CurElem, Result, MBB.back()); + } } } } - -} diff --git a/lib/CodeGen/AsmPrinter/DbgValueHistoryCalculator.h b/lib/CodeGen/AsmPrinter/DbgValueHistoryCalculator.h index b9177f0..4b62007 100644 --- a/lib/CodeGen/AsmPrinter/DbgValueHistoryCalculator.h +++ b/lib/CodeGen/AsmPrinter/DbgValueHistoryCalculator.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef CODEGEN_ASMPRINTER_DBGVALUEHISTORYCALCULATOR_H_ -#define CODEGEN_ASMPRINTER_DBGVALUEHISTORYCALCULATOR_H_ +#ifndef LLVM_LIB_CODEGEN_ASMPRINTER_DBGVALUEHISTORYCALCULATOR_H +#define LLVM_LIB_CODEGEN_ASMPRINTER_DBGVALUEHISTORYCALCULATOR_H #include "llvm/ADT/MapVector.h" #include "llvm/ADT/SmallVector.h" @@ -28,9 +28,11 @@ class DbgValueHistoryMap { // range. If end is not specified, location is valid until the start // instruction of the next instruction range, or until the end of the // function. +public: typedef std::pair<const MachineInstr *, const MachineInstr *> InstrRange; typedef SmallVector<InstrRange, 4> InstrRanges; typedef MapVector<const MDNode *, InstrRanges> InstrRangesMap; +private: InstrRangesMap VarInstrRanges; public: diff --git a/lib/CodeGen/AsmPrinter/DebugLocEntry.h b/lib/CodeGen/AsmPrinter/DebugLocEntry.h index 3beb799..6cca985 100644 --- a/lib/CodeGen/AsmPrinter/DebugLocEntry.h +++ b/lib/CodeGen/AsmPrinter/DebugLocEntry.h @@ -7,14 +7,14 @@ // //===----------------------------------------------------------------------===// -#ifndef CODEGEN_ASMPRINTER_DEBUGLOCENTRY_H__ -#define CODEGEN_ASMPRINTER_DEBUGLOCENTRY_H__ +#ifndef LLVM_LIB_CODEGEN_ASMPRINTER_DEBUGLOCENTRY_H +#define LLVM_LIB_CODEGEN_ASMPRINTER_DEBUGLOCENTRY_H #include "llvm/IR/Constants.h" +#include "llvm/IR/DebugInfo.h" #include "llvm/MC/MachineLocation.h" #include "llvm/MC/MCSymbol.h" namespace llvm { -class DwarfCompileUnit; class MDNode; /// \brief This struct describes location entries emitted in the .debug_loc /// section. @@ -26,25 +26,30 @@ class DebugLocEntry { public: /// A single location or constant. struct Value { - Value(const MDNode *Var, int64_t i) - : Variable(Var), EntryKind(E_Integer) { + Value(const MDNode *Var, const MDNode *Expr, int64_t i) + : Variable(Var), Expression(Expr), EntryKind(E_Integer) { Constant.Int = i; } - Value(const MDNode *Var, const ConstantFP *CFP) - : Variable(Var), EntryKind(E_ConstantFP) { + Value(const MDNode *Var, const MDNode *Expr, const ConstantFP *CFP) + : Variable(Var), Expression(Expr), EntryKind(E_ConstantFP) { Constant.CFP = CFP; } - Value(const MDNode *Var, const ConstantInt *CIP) - : Variable(Var), EntryKind(E_ConstantInt) { + Value(const MDNode *Var, const MDNode *Expr, const ConstantInt *CIP) + : Variable(Var), Expression(Expr), EntryKind(E_ConstantInt) { Constant.CIP = CIP; } - Value(const MDNode *Var, MachineLocation Loc) - : Variable(Var), EntryKind(E_Location), Loc(Loc) { + Value(const MDNode *Var, const MDNode *Expr, MachineLocation Loc) + : Variable(Var), Expression(Expr), EntryKind(E_Location), Loc(Loc) { + assert(DIVariable(Var).Verify()); + assert(DIExpression(Expr).Verify()); } // The variable to which this location entry corresponds. const MDNode *Variable; + // Any complex address location expression for this Value. + const MDNode *Expression; + // Type of entry that this represents. enum EntryType { E_Location, E_Integer, E_ConstantFP, E_ConstantInt }; enum EntryType EntryKind; @@ -59,23 +64,6 @@ public: // Or a location in the machine frame. MachineLocation Loc; - bool operator==(const Value &other) const { - if (EntryKind != other.EntryKind) - return false; - - 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"); - } - bool isLocation() const { return EntryKind == E_Location; } bool isInt() const { return EntryKind == E_Integer; } bool isConstantFP() const { return EntryKind == E_ConstantFP; } @@ -84,40 +72,114 @@ public: 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; } + const MDNode *getVariableNode() const { return Variable; } + DIVariable getVariable() const { return DIVariable(Variable); } + bool isVariablePiece() const { return getExpression().isVariablePiece(); } + DIExpression getExpression() const { return DIExpression(Expression); } + friend bool operator==(const Value &, const Value &); + friend bool operator<(const Value &, const Value &); }; + private: - /// A list of locations/constants belonging to this entry. + /// A nonempty list of locations/constants belonging to this entry, + /// sorted by offset. SmallVector<Value, 1> Values; - /// The compile unit that this location entry is referenced by. - const DwarfCompileUnit *Unit; - public: - 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) { + DebugLocEntry(const MCSymbol *B, const MCSymbol *E, Value Val) + : Begin(B), End(E) { Values.push_back(std::move(Val)); } + /// \brief If this and Next are describing different pieces of the same + // variable, merge them by appending Next's values to the current + // list of values. + // Return true if the merge was successful. + bool MergeValues(const DebugLocEntry &Next) { + if (Begin == Next.Begin) { + DIExpression Expr(Values[0].Expression); + DIVariable Var(Values[0].Variable); + DIExpression NextExpr(Next.Values[0].Expression); + DIVariable NextVar(Next.Values[0].Variable); + if (Var == NextVar && Expr.isVariablePiece() && + NextExpr.isVariablePiece()) { + addValues(Next.Values); + End = Next.End; + return true; + } + } + return false; + } + /// \brief Attempt to merge this DebugLocEntry with Next and return /// true if the merge was successful. Entries can be merged if they /// share the same Loc/Constant and if Next immediately follows this /// Entry. - bool Merge(const DebugLocEntry &Next) { + bool MergeRanges(const DebugLocEntry &Next) { + // If this and Next are describing the same variable, merge them. if ((End == Next.Begin && Values == Next.Values)) { End = Next.End; return true; } return false; } + const MCSymbol *getBeginSym() const { return Begin; } const MCSymbol *getEndSym() const { return End; } - const DwarfCompileUnit *getCU() const { return Unit; } - const ArrayRef<Value> getValues() const { return Values; } - void addValue(Value Val) { Values.push_back(Val); } + ArrayRef<Value> getValues() const { return Values; } + void addValues(ArrayRef<DebugLocEntry::Value> Vals) { + Values.append(Vals.begin(), Vals.end()); + sortUniqueValues(); + assert(std::all_of(Values.begin(), Values.end(), [](DebugLocEntry::Value V){ + return V.isVariablePiece(); + }) && "value must be a piece"); + } + + // Sort the pieces by offset. + // Remove any duplicate entries by dropping all but the first. + void sortUniqueValues() { + std::sort(Values.begin(), Values.end()); + Values.erase(std::unique(Values.begin(), Values.end(), + [](const Value &A, const Value &B) { + return A.getVariable() == B.getVariable() && + A.getExpression() == B.getExpression(); + }), + Values.end()); + } }; +/// Compare two Values for equality. +inline bool operator==(const DebugLocEntry::Value &A, + const DebugLocEntry::Value &B) { + if (A.EntryKind != B.EntryKind) + return false; + + if (A.Expression != B.Expression) + return false; + + if (A.Variable != B.Variable) + return false; + + switch (A.EntryKind) { + case DebugLocEntry::Value::E_Location: + return A.Loc == B.Loc; + case DebugLocEntry::Value::E_Integer: + return A.Constant.Int == B.Constant.Int; + case DebugLocEntry::Value::E_ConstantFP: + return A.Constant.CFP == B.Constant.CFP; + case DebugLocEntry::Value::E_ConstantInt: + return A.Constant.CIP == B.Constant.CIP; + } + llvm_unreachable("unhandled EntryKind"); +} + +/// Compare two pieces based on their offset. +inline bool operator<(const DebugLocEntry::Value &A, + const DebugLocEntry::Value &B) { + return A.getExpression().getPieceOffset() < + B.getExpression().getPieceOffset(); } + +} + #endif diff --git a/lib/CodeGen/AsmPrinter/DebugLocList.h b/lib/CodeGen/AsmPrinter/DebugLocList.h index 7a51c7b..2a4f58f 100644 --- a/lib/CodeGen/AsmPrinter/DebugLocList.h +++ b/lib/CodeGen/AsmPrinter/DebugLocList.h @@ -7,16 +7,18 @@ // //===----------------------------------------------------------------------===// -#ifndef CODEGEN_ASMPRINTER_DEBUGLOCLIST_H__ -#define CODEGEN_ASMPRINTER_DEBUGLOCLIST_H__ +#ifndef LLVM_LIB_CODEGEN_ASMPRINTER_DEBUGLOCLIST_H +#define LLVM_LIB_CODEGEN_ASMPRINTER_DEBUGLOCLIST_H -#include "llvm/MC/MCSymbol.h" #include "llvm/ADT/SmallVector.h" #include "DebugLocEntry.h" namespace llvm { +class DwarfCompileUnit; +class MCSymbol; struct DebugLocList { MCSymbol *Label; + DwarfCompileUnit *CU; SmallVector<DebugLocEntry, 4> List; }; } diff --git a/lib/CodeGen/AsmPrinter/DwarfAccelTable.cpp b/lib/CodeGen/AsmPrinter/DwarfAccelTable.cpp index e9527c4..7e87566 100644 --- a/lib/CodeGen/AsmPrinter/DwarfAccelTable.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfAccelTable.cpp @@ -13,6 +13,7 @@ #include "DwarfAccelTable.h" #include "DIE.h" +#include "DwarfCompileUnit.h" #include "DwarfDebug.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/Twine.h" @@ -174,7 +175,8 @@ void DwarfAccelTable::EmitOffsets(AsmPrinter *Asm, MCSymbol *SecBegin) { // Walk through the buckets and emit the full data for each element in // the bucket. For the string case emit the dies and the various offsets. // Terminate each HashData bucket with 0. -void DwarfAccelTable::EmitData(AsmPrinter *Asm, DwarfFile *D) { +void DwarfAccelTable::EmitData(AsmPrinter *Asm, DwarfDebug *D, + MCSymbol *StrSym) { uint64_t PrevHash = UINT64_MAX; for (size_t i = 0, e = Buckets.size(); i < e; ++i) { for (HashList::const_iterator HI = Buckets[i].begin(), @@ -183,13 +185,14 @@ 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((*HI)->Data.StrSym, - D->getStringPool().getSectionSymbol()); + Asm->EmitSectionOffset((*HI)->Data.StrSym, StrSym); Asm->OutStreamer.AddComment("Num DIEs"); Asm->EmitInt32((*HI)->Data.Values.size()); for (HashDataContents *HD : (*HI)->Data.Values) { // Emit the DIE offset - Asm->EmitInt32(HD->Die->getOffset()); + DwarfCompileUnit *CU = D->lookupUnit(HD->Die->getUnit()); + assert(CU && "Accelerated DIE should belong to a CU."); + Asm->EmitInt32(HD->Die->getOffset() + CU->getDebugInfoOffset()); // 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) { @@ -206,7 +209,8 @@ void DwarfAccelTable::EmitData(AsmPrinter *Asm, DwarfFile *D) { } // Emit the entire data structure to the output file. -void DwarfAccelTable::Emit(AsmPrinter *Asm, MCSymbol *SecBegin, DwarfFile *D) { +void DwarfAccelTable::Emit(AsmPrinter *Asm, MCSymbol *SecBegin, DwarfDebug *D, + MCSymbol *StrSym) { // Emit the header. EmitHeader(Asm); @@ -220,7 +224,7 @@ void DwarfAccelTable::Emit(AsmPrinter *Asm, MCSymbol *SecBegin, DwarfFile *D) { EmitOffsets(Asm, SecBegin); // Emit the hash data. - EmitData(Asm, D); + EmitData(Asm, D, StrSym); } #ifndef NDEBUG diff --git a/lib/CodeGen/AsmPrinter/DwarfAccelTable.h b/lib/CodeGen/AsmPrinter/DwarfAccelTable.h index a3cc95f..3cdf678 100644 --- a/lib/CodeGen/AsmPrinter/DwarfAccelTable.h +++ b/lib/CodeGen/AsmPrinter/DwarfAccelTable.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef CODEGEN_ASMPRINTER_DWARFACCELTABLE_H__ -#define CODEGEN_ASMPRINTER_DWARFACCELTABLE_H__ +#ifndef LLVM_LIB_CODEGEN_ASMPRINTER_DWARFACCELTABLE_H +#define LLVM_LIB_CODEGEN_ASMPRINTER_DWARFACCELTABLE_H #include "DIE.h" #include "llvm/ADT/ArrayRef.h" @@ -62,7 +62,7 @@ namespace llvm { class AsmPrinter; -class DwarfFile; +class DwarfDebug; class DwarfAccelTable { @@ -140,7 +140,7 @@ public: private: struct TableHeaderData { uint32_t die_offset_base; - SmallVector<Atom, 1> Atoms; + SmallVector<Atom, 3> Atoms; TableHeaderData(ArrayRef<Atom> AtomList, uint32_t offset = 0) : die_offset_base(offset), Atoms(AtomList.begin(), AtomList.end()) {} @@ -223,7 +223,7 @@ private: void EmitBuckets(AsmPrinter *); void EmitHashes(AsmPrinter *); void EmitOffsets(AsmPrinter *, MCSymbol *); - void EmitData(AsmPrinter *, DwarfFile *D); + void EmitData(AsmPrinter *, DwarfDebug *D, MCSymbol *StrSym); // Allocator for HashData and HashDataContents. BumpPtrAllocator Allocator; @@ -248,7 +248,7 @@ public: void AddName(StringRef Name, MCSymbol *StrSym, const DIE *Die, char Flags = 0); void FinalizeTable(AsmPrinter *, StringRef); - void Emit(AsmPrinter *, MCSymbol *, DwarfFile *); + void Emit(AsmPrinter *, MCSymbol *, DwarfDebug *, MCSymbol *StrSym); #ifndef NDEBUG void print(raw_ostream &O); void dump() { print(dbgs()); } diff --git a/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp b/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp index 74215aa..0dc52da 100644 --- a/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp @@ -51,7 +51,7 @@ void DwarfCFIException::endModule() { if (moveTypeModule == AsmPrinter::CFI_M_Debug) Asm->OutStreamer.EmitCFISections(false, true); - if (!Asm->MAI->isExceptionHandlingDwarf()) + if (!Asm->MAI->usesItaniumLSDAForExceptions()) return; const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering(); diff --git a/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp b/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp new file mode 100644 index 0000000..2f1b0e5 --- /dev/null +++ b/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp @@ -0,0 +1,862 @@ +#include "DwarfCompileUnit.h" + +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/IR/GlobalValue.h" +#include "llvm/IR/GlobalVariable.h" +#include "llvm/IR/Instruction.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/Target/TargetFrameLowering.h" +#include "llvm/Target/TargetLoweringObjectFile.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetSubtargetInfo.h" +#include "llvm/Target/TargetRegisterInfo.h" + +namespace llvm { + +DwarfCompileUnit::DwarfCompileUnit(unsigned UID, DICompileUnit Node, + AsmPrinter *A, DwarfDebug *DW, + DwarfFile *DWU) + : DwarfUnit(UID, dwarf::DW_TAG_compile_unit, Node, A, DW, DWU), + Skeleton(nullptr), LabelBegin(nullptr), BaseAddress(nullptr) { + insertDIE(Node, &getUnitDie()); +} + +/// 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, + const MCSymbol *Label) { + + // Don't use the address pool in non-fission or in the skeleton unit itself. + // FIXME: Once GDB supports this, it's probably worthwhile using the address + // pool from the skeleton - maybe even in non-fission (possibly fewer + // relocations by sharing them in the pool, but we have other ideas about how + // to reduce the number of relocations as well/instead). + if (!DD->useSplitDwarf() || !Skeleton) + return addLocalLabelAddress(Die, Attribute, Label); + + if (Label) + DD->addArangeLabel(SymbolCU(this, Label)); + + unsigned idx = DD->getAddressPool().getIndex(Label); + DIEValue *Value = new (DIEValueAllocator) DIEInteger(idx); + Die.addValue(Attribute, dwarf::DW_FORM_GNU_addr_index, Value); +} + +void DwarfCompileUnit::addLocalLabelAddress(DIE &Die, + dwarf::Attribute Attribute, + const MCSymbol *Label) { + if (Label) + DD->addArangeLabel(SymbolCU(this, Label)); + + Die.addValue(Attribute, dwarf::DW_FORM_addr, + Label ? (DIEValue *)new (DIEValueAllocator) DIELabel(Label) + : new (DIEValueAllocator) DIEInteger(0)); +} + +unsigned DwarfCompileUnit::getOrCreateSourceID(StringRef FileName, + StringRef DirName) { + // If we print assembly, we can't separate .file entries according to + // compile units. Thus all files will belong to the default compile unit. + + // FIXME: add a better feature test than hasRawTextSupport. Even better, + // extend .file to support this. + return Asm->OutStreamer.EmitDwarfFileDirective( + 0, DirName, FileName, + Asm->OutStreamer.hasRawTextSupport() ? 0 : getUniqueID()); +} + +// Return const expression if value is a GEP to access merged global +// constant. e.g. +// i8* getelementptr ({ i8, i8, i8, i8 }* @_MergedGlobals, i32 0, i32 0) +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 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 nullptr; + + // Second operand is zero. + const ConstantInt *CI = dyn_cast_or_null<ConstantInt>(CE->getOperand(1)); + if (!CI || !CI->isZero()) + return nullptr; + + // Third operand is offset. + if (!isa<ConstantInt>(CE->getOperand(2))) + return nullptr; + + return CE; +} + +/// getOrCreateGlobalVariableDIE - get or create global variable DIE. +DIE *DwarfCompileUnit::getOrCreateGlobalVariableDIE(DIGlobalVariable GV) { + // Check for pre-existence. + if (DIE *Die = getDIE(GV)) + return Die; + + assert(GV.isGlobalVariable()); + + DIScope GVContext = DD->resolve(GV.getContext()); + DIType GTy = DD->resolve(GV.getType()); + + // Construct the context before querying for the existence of the DIE in + // case such construction creates the DIE. + DIE *ContextDIE = getOrCreateContextDIE(GVContext); + + // Add to map. + DIE *VariableDIE = &createAndAddDIE(GV.getTag(), *ContextDIE, GV); + DIScope DeclContext; + + if (DIDerivedType SDMDecl = GV.getStaticDataMemberDeclaration()) { + DeclContext = resolve(SDMDecl.getContext()); + assert(SDMDecl.isStaticMember() && "Expected static member decl"); + assert(GV.isDefinition()); + // We need the declaration DIE that is in the static member's class. + DIE *VariableSpecDIE = getOrCreateStaticMemberDIE(SDMDecl); + addDIEEntry(*VariableDIE, dwarf::DW_AT_specification, *VariableSpecDIE); + } else { + DeclContext = resolve(GV.getContext()); + // Add name and type. + addString(*VariableDIE, dwarf::DW_AT_name, GV.getDisplayName()); + addType(*VariableDIE, GTy); + + // Add scoping info. + if (!GV.isLocalToUnit()) + addFlag(*VariableDIE, dwarf::DW_AT_external); + + // Add line number info. + addSourceLine(*VariableDIE, GV); + } + + if (!GV.isDefinition()) + addFlag(*VariableDIE, dwarf::DW_AT_declaration); + + // Add location. + bool addToAccelTable = false; + bool isGlobalVariable = GV.getGlobal() != nullptr; + if (isGlobalVariable) { + addToAccelTable = true; + DIELoc *Loc = new (DIEValueAllocator) DIELoc(); + const MCSymbol *Sym = Asm->getSymbol(GV.getGlobal()); + if (GV.getGlobal()->isThreadLocal()) { + // FIXME: Make this work with -gsplit-dwarf. + unsigned PointerSize = Asm->getDataLayout().getPointerSize(); + assert((PointerSize == 4 || PointerSize == 8) && + "Add support for other sizes if necessary"); + // 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, + 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, + Asm->getObjFileLowering().getDebugThreadLocalSymbol(Sym)); + } else { + 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); + } else { + DD->addArangeLabel(SymbolCU(this, Sym)); + addOpAddress(*Loc, Sym); + } + + addBlock(*VariableDIE, dwarf::DW_AT_location, Loc); + // Add the linkage name. + StringRef LinkageName = GV.getLinkageName(); + if (!LinkageName.empty()) + // 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(*VariableDIE, + DD->getDwarfVersion() >= 4 ? dwarf::DW_AT_linkage_name + : dwarf::DW_AT_MIPS_linkage_name, + GlobalValue::getRealLinkageName(LinkageName)); + } else if (const ConstantInt *CI = + dyn_cast_or_null<ConstantInt>(GV.getConstant())) { + addConstantValue(*VariableDIE, CI, GTy); + } else if (const ConstantExpr *CE = getMergedGlobalExpr(GV.getConstant())) { + addToAccelTable = true; + // GV is a merged global. + DIELoc *Loc = new (DIEValueAllocator) DIELoc(); + 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); + SmallVector<Value *, 3> Idx(CE->op_begin() + 1, CE->op_end()); + 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); + } + + if (addToAccelTable) { + DD->addAccelName(GV.getName(), *VariableDIE); + + // If the linkage name is different than the name, go ahead and output + // that as well into the name table. + if (GV.getLinkageName() != "" && GV.getName() != GV.getLinkageName()) + DD->addAccelName(GV.getLinkageName(), *VariableDIE); + } + + addGlobalName(GV.getName(), *VariableDIE, DeclContext); + return VariableDIE; +} + +void DwarfCompileUnit::addRange(RangeSpan Range) { + bool SameAsPrevCU = this == DD->getPrevCU(); + DD->setPrevCU(this); + // If we have no current ranges just add the range and return, otherwise, + // check the current section and CU against the previous section and CU we + // emitted into and the subprogram was contained within. If these are the + // same then extend our current range, otherwise add this as a new range. + if (CURanges.empty() || !SameAsPrevCU || + (&CURanges.back().getEnd()->getSection() != + &Range.getEnd()->getSection())) { + CURanges.push_back(Range); + return; + } + + CURanges.back().setEnd(Range.getEnd()); +} + +void DwarfCompileUnit::addSectionLabel(DIE &Die, dwarf::Attribute Attribute, + const MCSymbol *Label, + const MCSymbol *Sec) { + if (Asm->MAI->doesDwarfUseRelocationsAcrossSections()) + addLabel(Die, Attribute, + DD->getDwarfVersion() >= 4 ? dwarf::DW_FORM_sec_offset + : dwarf::DW_FORM_data4, + Label); + else + addSectionDelta(Die, Attribute, Label, Sec); +} + +void DwarfCompileUnit::initStmtList(MCSymbol *DwarfLineSectionSym) { + // Define start line table label for each Compile Unit. + MCSymbol *LineTableStartSym = + Asm->OutStreamer.getDwarfLineTableSymbol(getUniqueID()); + + stmtListIndex = UnitDie.getValues().size(); + + // DW_AT_stmt_list is a offset of line number information for this + // compile unit in debug_line section. For split dwarf this is + // left in the skeleton CU and so not included. + // The line table entries are not always emitted in assembly, so it + // is not okay to use line_table_start here. + addSectionLabel(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]); +} + +void DwarfCompileUnit::attachLowHighPC(DIE &D, const MCSymbol *Begin, + const MCSymbol *End) { + 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"); + + addLabelAddress(D, dwarf::DW_AT_low_pc, Begin); + if (DD->getDwarfVersion() < 4) + addLabelAddress(D, dwarf::DW_AT_high_pc, End); + else + addLabelDelta(D, dwarf::DW_AT_high_pc, End, Begin); +} + +// 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 &DwarfCompileUnit::updateSubprogramScopeDIE(DISubprogram SP) { + DIE *SPDie = getOrCreateSubprogramDIE(SP, includeMinimalInlineScopes()); + + attachLowHighPC(*SPDie, DD->getFunctionBeginSym(), DD->getFunctionEndSym()); + if (!DD->getCurrentFunction()->getTarget().Options.DisableFramePointerElim( + *DD->getCurrentFunction())) + addFlag(*SPDie, dwarf::DW_AT_APPLE_omit_frame_ptr); + + // Only include DW_AT_frame_base in full debug info + if (!includeMinimalInlineScopes()) { + const TargetRegisterInfo *RI = + Asm->TM.getSubtargetImpl()->getRegisterInfo(); + MachineLocation Location(RI->getFrameRegister(*Asm->MF)); + 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. + DD->addSubprogramNames(SP, *SPDie); + + return *SPDie; +} + +// Construct a DIE for this scope. +void DwarfCompileUnit::constructScopeDIE( + LexicalScope *Scope, SmallVectorImpl<std::unique_ptr<DIE>> &FinalChildren) { + if (!Scope || !Scope->getScopeNode()) + return; + + DIScope DS(Scope->getScopeNode()); + + 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. + std::unique_ptr<DIE> ScopeDIE; + if (Scope->getParent() && DS.isSubprogram()) { + ScopeDIE = constructInlinedScopeDIE(Scope); + if (!ScopeDIE) + return; + // We create children when the scope DIE is not null. + createScopeChildrenDIE(Scope, Children); + } else { + // Early exit when we know the scope DIE is going to be null. + if (DD->isLexicalScopeDIENull(Scope)) + return; + + unsigned ChildScopeCount; + + // 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. + createScopeChildrenDIE(Scope, Children, &ChildScopeCount); + + // Skip imported directives in gmlt-like data. + if (!includeMinimalInlineScopes()) { + // There is no need to emit empty lexical block DIE. + for (const auto &E : DD->findImportedEntitiesForScope(DS)) + Children.push_back( + constructImportedEntityDIE(DIImportedEntity(E.second))); + } + + // If there are only other scopes as children, put them directly in the + // parent instead, as this scope would serve no purpose. + if (Children.size() == ChildScopeCount) { + FinalChildren.insert(FinalChildren.end(), + std::make_move_iterator(Children.begin()), + std::make_move_iterator(Children.end())); + return; + } + ScopeDIE = constructLexicalScopeDIE(Scope); + assert(ScopeDIE && "Scope DIE should not be null."); + } + + // Add children + for (auto &I : Children) + ScopeDIE->addChild(std::move(I)); + + FinalChildren.push_back(std::move(ScopeDIE)); +} + +void DwarfCompileUnit::addSectionDelta(DIE &Die, dwarf::Attribute Attribute, + const MCSymbol *Hi, const MCSymbol *Lo) { + DIEValue *Value = new (DIEValueAllocator) DIEDelta(Hi, Lo); + Die.addValue(Attribute, DD->getDwarfVersion() >= 4 ? dwarf::DW_FORM_sec_offset + : dwarf::DW_FORM_data4, + Value); +} + +void DwarfCompileUnit::addScopeRangeList(DIE &ScopeDIE, + SmallVector<RangeSpan, 2> Range) { + // Emit offset in .debug_range as a relocatable label. emitDIE will handle + // emitting it appropriately. + auto *RangeSectionSym = DD->getRangeSectionSym(); + + RangeSpanList List( + Asm->GetTempSymbol("debug_ranges", DD->getNextRangeNumber()), + std::move(Range)); + + // Under fission, ranges are specified by constant offsets relative to the + // CU's DW_AT_GNU_ranges_base. + if (isDwoUnit()) + addSectionDelta(ScopeDIE, dwarf::DW_AT_ranges, List.getSym(), + RangeSectionSym); + else + addSectionLabel(ScopeDIE, dwarf::DW_AT_ranges, List.getSym(), + RangeSectionSym); + + // Add the range list to the set of ranges to be emitted. + (Skeleton ? Skeleton : this)->CURangeLists.push_back(std::move(List)); +} + +void DwarfCompileUnit::attachRangesOrLowHighPC( + DIE &Die, SmallVector<RangeSpan, 2> Ranges) { + if (Ranges.size() == 1) { + const auto &single = Ranges.front(); + attachLowHighPC(Die, single.getStart(), single.getEnd()); + } else + addScopeRangeList(Die, std::move(Ranges)); +} + +void DwarfCompileUnit::attachRangesOrLowHighPC( + DIE &Die, const SmallVectorImpl<InsnRange> &Ranges) { + SmallVector<RangeSpan, 2> List; + List.reserve(Ranges.size()); + for (const InsnRange &R : Ranges) + List.push_back(RangeSpan(DD->getLabelBeforeInsn(R.first), + DD->getLabelAfterInsn(R.second))); + attachRangesOrLowHighPC(Die, std::move(List)); +} + +// This scope represents inlined body of a function. Construct DIE to +// represent this concrete inlined copy of the function. +std::unique_ptr<DIE> +DwarfCompileUnit::constructInlinedScopeDIE(LexicalScope *Scope) { + assert(Scope->getScopeNode()); + DIScope DS(Scope->getScopeNode()); + DISubprogram InlinedSP = getDISubprogram(DS); + // Find the subprogram's DwarfCompileUnit in the SPMap in case the subprogram + // was inlined from another compile unit. + DIE *OriginDIE = DU->getAbstractSPDies()[InlinedSP]; + assert(OriginDIE && "Unable to find original DIE for an inlined subprogram."); + + auto ScopeDIE = make_unique<DIE>(dwarf::DW_TAG_inlined_subroutine); + addDIEEntry(*ScopeDIE, dwarf::DW_AT_abstract_origin, *OriginDIE); + + attachRangesOrLowHighPC(*ScopeDIE, Scope->getRanges()); + + // Add the call site information to the DIE. + DILocation DL(Scope->getInlinedAt()); + addUInt(*ScopeDIE, dwarf::DW_AT_call_file, None, + getOrCreateSourceID(DL.getFilename(), DL.getDirectory())); + 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. + DD->addSubprogramNames(InlinedSP, *ScopeDIE); + + return ScopeDIE; +} + +// Construct new DW_TAG_lexical_block for this scope and attach +// DW_AT_low_pc/DW_AT_high_pc labels. +std::unique_ptr<DIE> +DwarfCompileUnit::constructLexicalScopeDIE(LexicalScope *Scope) { + if (DD->isLexicalScopeDIENull(Scope)) + return nullptr; + + auto ScopeDIE = make_unique<DIE>(dwarf::DW_TAG_lexical_block); + if (Scope->isAbstractScope()) + return ScopeDIE; + + attachRangesOrLowHighPC(*ScopeDIE, Scope->getRanges()); + + return ScopeDIE; +} + +/// constructVariableDIE - Construct a DIE for the given DbgVariable. +std::unique_ptr<DIE> DwarfCompileUnit::constructVariableDIE(DbgVariable &DV, + bool Abstract) { + auto D = constructVariableDIEImpl(DV, Abstract); + DV.setDIE(*D); + return D; +} + +std::unique_ptr<DIE> +DwarfCompileUnit::constructVariableDIEImpl(const DbgVariable &DV, + bool Abstract) { + // Define variable debug information entry. + auto VariableDie = make_unique<DIE>(DV.getTag()); + + if (Abstract) { + applyVariableAttributes(DV, *VariableDie); + return VariableDie; + } + + // Add variable address. + + unsigned Offset = DV.getDotDebugLocOffset(); + if (Offset != ~0U) { + addLocationList(*VariableDie, dwarf::DW_AT_location, Offset); + return VariableDie; + } + + // Check if variable is described by a DBG_VALUE instruction. + if (const MachineInstr *DVInsn = DV.getMInsn()) { + assert(DVInsn->getNumOperands() == 4); + if (DVInsn->getOperand(0).isReg()) { + const MachineOperand RegOp = DVInsn->getOperand(0); + // If the second operand is an immediate, this is an indirect value. + if (DVInsn->getOperand(1).isImm()) { + MachineLocation Location(RegOp.getReg(), + DVInsn->getOperand(1).getImm()); + addVariableAddress(DV, *VariableDie, Location); + } else if (RegOp.getReg()) + addVariableAddress(DV, *VariableDie, MachineLocation(RegOp.getReg())); + } else if (DVInsn->getOperand(0).isImm()) + addConstantValue(*VariableDie, DVInsn->getOperand(0), DV.getType()); + else if (DVInsn->getOperand(0).isFPImm()) + addConstantFPValue(*VariableDie, DVInsn->getOperand(0)); + else if (DVInsn->getOperand(0).isCImm()) + addConstantValue(*VariableDie, DVInsn->getOperand(0).getCImm(), + DV.getType()); + + return VariableDie; + } + + // .. else use frame index. + int FI = DV.getFrameIndex(); + if (FI != ~0) { + unsigned FrameReg = 0; + const TargetFrameLowering *TFI = + Asm->TM.getSubtargetImpl()->getFrameLowering(); + int Offset = TFI->getFrameIndexReference(*Asm->MF, FI, FrameReg); + MachineLocation Location(FrameReg, Offset); + addVariableAddress(DV, *VariableDie, Location); + } + + return VariableDie; +} + +std::unique_ptr<DIE> DwarfCompileUnit::constructVariableDIE( + DbgVariable &DV, const LexicalScope &Scope, DIE *&ObjectPointer) { + auto Var = constructVariableDIE(DV, Scope.isAbstractScope()); + if (DV.isObjectPointer()) + ObjectPointer = Var.get(); + return Var; +} + +DIE *DwarfCompileUnit::createScopeChildrenDIE( + LexicalScope *Scope, SmallVectorImpl<std::unique_ptr<DIE>> &Children, + unsigned *ChildScopeCount) { + DIE *ObjectPointer = nullptr; + + for (DbgVariable *DV : DU->getScopeVariables().lookup(Scope)) + Children.push_back(constructVariableDIE(*DV, *Scope, ObjectPointer)); + + unsigned ChildCountWithoutScopes = Children.size(); + + for (LexicalScope *LS : Scope->getChildren()) + constructScopeDIE(LS, Children); + + if (ChildScopeCount) + *ChildScopeCount = Children.size() - ChildCountWithoutScopes; + + return ObjectPointer; +} + +void DwarfCompileUnit::constructSubprogramScopeDIE(LexicalScope *Scope) { + assert(Scope && Scope->getScopeNode()); + assert(!Scope->getInlinedAt()); + assert(!Scope->isAbstractScope()); + DISubprogram Sub(Scope->getScopeNode()); + + assert(Sub.isSubprogram()); + + DD->getProcessedSPNodes().insert(Sub); + + DIE &ScopeDIE = updateSubprogramScopeDIE(Sub); + + // If this is a variadic function, add an unspecified parameter. + DITypeArray FnArgs = Sub.getType().getTypeArray(); + + // Collect lexical scope children first. + // ObjectPointer might be a local (non-argument) local variable if it's a + // block's synthetic this pointer. + if (DIE *ObjectPointer = createAndAddScopeChildren(Scope, ScopeDIE)) + addDIEEntry(ScopeDIE, dwarf::DW_AT_object_pointer, *ObjectPointer); + + // If we have a single element of null, it is a function that returns void. + // If we have more than one elements and the last one is null, it is a + // variadic function. + if (FnArgs.getNumElements() > 1 && + !FnArgs.getElement(FnArgs.getNumElements() - 1) && + !includeMinimalInlineScopes()) + ScopeDIE.addChild(make_unique<DIE>(dwarf::DW_TAG_unspecified_parameters)); +} + +DIE *DwarfCompileUnit::createAndAddScopeChildren(LexicalScope *Scope, + DIE &ScopeDIE) { + // We create children when the scope DIE is not null. + SmallVector<std::unique_ptr<DIE>, 8> Children; + DIE *ObjectPointer = createScopeChildrenDIE(Scope, Children); + + // Add children + for (auto &I : Children) + ScopeDIE.addChild(std::move(I)); + + return ObjectPointer; +} + +void +DwarfCompileUnit::constructAbstractSubprogramScopeDIE(LexicalScope *Scope) { + DIE *&AbsDef = DU->getAbstractSPDies()[Scope->getScopeNode()]; + if (AbsDef) + return; + + DISubprogram SP(Scope->getScopeNode()); + + DIE *ContextDIE; + + if (includeMinimalInlineScopes()) + ContextDIE = &getUnitDie(); + // 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. + else if (DISubprogram SPDecl = SP.getFunctionDeclaration()) { + ContextDIE = &getUnitDie(); + getOrCreateSubprogramDIE(SPDecl); + } else + ContextDIE = getOrCreateContextDIE(resolve(SP.getContext())); + + // Passing null as the associated DIDescriptor because the abstract definition + // shouldn't be found by lookup. + AbsDef = + &createAndAddDIE(dwarf::DW_TAG_subprogram, *ContextDIE, DIDescriptor()); + applySubprogramAttributesToDefinition(SP, *AbsDef); + + if (!includeMinimalInlineScopes()) + addUInt(*AbsDef, dwarf::DW_AT_inline, None, dwarf::DW_INL_inlined); + if (DIE *ObjectPointer = createAndAddScopeChildren(Scope, *AbsDef)) + addDIEEntry(*AbsDef, dwarf::DW_AT_object_pointer, *ObjectPointer); +} + +std::unique_ptr<DIE> +DwarfCompileUnit::constructImportedEntityDIE(const DIImportedEntity &Module) { + assert(Module.Verify() && + "Use one of the MDNode * overloads to handle invalid metadata"); + std::unique_ptr<DIE> IMDie = make_unique<DIE>((dwarf::Tag)Module.getTag()); + insertDIE(Module, IMDie.get()); + DIE *EntityDie; + DIDescriptor Entity = resolve(Module.getEntity()); + if (Entity.isNameSpace()) + EntityDie = getOrCreateNameSpace(DINameSpace(Entity)); + else if (Entity.isSubprogram()) + EntityDie = getOrCreateSubprogramDIE(DISubprogram(Entity)); + else if (Entity.isType()) + EntityDie = getOrCreateTypeDIE(DIType(Entity)); + else if (Entity.isGlobalVariable()) + EntityDie = getOrCreateGlobalVariableDIE(DIGlobalVariable(Entity)); + else + EntityDie = getDIE(Entity); + assert(EntityDie); + addSourceLine(*IMDie, Module.getLineNumber(), + Module.getContext().getFilename(), + Module.getContext().getDirectory()); + addDIEEntry(*IMDie, dwarf::DW_AT_import, *EntityDie); + StringRef Name = Module.getName(); + if (!Name.empty()) + addString(*IMDie, dwarf::DW_AT_name, Name); + + return IMDie; +} + +void DwarfCompileUnit::finishSubprogramDefinition(DISubprogram SP) { + DIE *D = getDIE(SP); + if (DIE *AbsSPDIE = DU->getAbstractSPDies().lookup(SP)) { + if (D) + // If this subprogram has an abstract definition, reference that + addDIEEntry(*D, dwarf::DW_AT_abstract_origin, *AbsSPDIE); + } else { + if (!D && !includeMinimalInlineScopes()) + // Lazily construct the subprogram if we didn't see either concrete or + // inlined versions during codegen. (except in -gmlt ^ where we want + // to omit these entirely) + D = getOrCreateSubprogramDIE(SP); + if (D) + // And attach the attributes + applySubprogramAttributesToDefinition(SP, *D); + } +} +void DwarfCompileUnit::collectDeadVariables(DISubprogram SP) { + 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) + return; + + DIE *SPDIE = DU->getAbstractSPDies().lookup(SP); + if (!SPDIE) + SPDIE = getDIE(SP); + assert(SPDIE); + for (unsigned vi = 0, ve = Variables.getNumElements(); vi != ve; ++vi) { + DIVariable DV(Variables.getElement(vi)); + assert(DV.isVariable()); + DbgVariable NewVar(DV, DIExpression(nullptr), DD); + auto VariableDie = constructVariableDIE(NewVar); + applyVariableAttributes(NewVar, *VariableDie); + SPDIE->addChild(std::move(VariableDie)); + } +} + +void DwarfCompileUnit::emitHeader(const MCSymbol *ASectionSym) const { + // Don't bother labeling the .dwo unit, as its offset isn't used. + if (!Skeleton) + Asm->OutStreamer.EmitLabel(LabelBegin); + + DwarfUnit::emitHeader(ASectionSym); +} + +/// addGlobalName - Add a new global name to the compile unit. +void DwarfCompileUnit::addGlobalName(StringRef Name, DIE &Die, + DIScope Context) { + if (includeMinimalInlineScopes()) + return; + std::string FullName = getParentContextString(Context) + Name.str(); + GlobalNames[FullName] = &Die; +} + +/// Add a new global type to the unit. +void DwarfCompileUnit::addGlobalType(DIType Ty, const DIE &Die, + DIScope Context) { + if (includeMinimalInlineScopes()) + return; + std::string FullName = getParentContextString(Context) + Ty.getName().str(); + GlobalTypes[FullName] = &Die; +} + +/// addVariableAddress - Add DW_AT_location attribute for a +/// DbgVariable based on provided MachineLocation. +void DwarfCompileUnit::addVariableAddress(const DbgVariable &DV, DIE &Die, + MachineLocation Location) { + if (DV.variableHasComplexAddress()) + addComplexAddress(DV, Die, dwarf::DW_AT_location, Location); + else if (DV.isBlockByrefVariable()) + addBlockByrefAddress(DV, Die, dwarf::DW_AT_location, Location); + else + addAddress(Die, dwarf::DW_AT_location, Location, + DV.getVariable().isIndirect()); +} + +/// Add an address attribute to a die based on the location provided. +void DwarfCompileUnit::addAddress(DIE &Die, dwarf::Attribute Attribute, + const MachineLocation &Location, + bool Indirect) { + DIELoc *Loc = new (DIEValueAllocator) DIELoc(); + + if (Location.isReg() && !Indirect) + addRegisterOpPiece(*Loc, Location.getReg()); + else { + addRegisterOffset(*Loc, Location.getReg(), Location.getOffset()); + if (Indirect && !Location.isReg()) { + addUInt(*Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_deref); + } + } + + // Now attach the location information to the DIE. + addBlock(Die, Attribute, Loc); +} + +/// Start with the address based on the location provided, and generate the +/// DWARF information necessary to find the actual variable given the extra +/// address information encoded in the DbgVariable, starting from the starting +/// location. Add the DWARF information to the die. +void DwarfCompileUnit::addComplexAddress(const DbgVariable &DV, DIE &Die, + dwarf::Attribute Attribute, + const MachineLocation &Location) { + DIELoc *Loc = new (DIEValueAllocator) DIELoc(); + unsigned N = DV.getNumAddrElements(); + unsigned i = 0; + if (Location.isReg()) { + if (N >= 2 && DV.getAddrElement(0) == dwarf::DW_OP_plus) { + assert(!DV.getVariable().isIndirect() && + "double indirection not handled"); + // 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)); + i = 2; + } else if (N >= 2 && DV.getAddrElement(0) == dwarf::DW_OP_deref) { + assert(!DV.getVariable().isIndirect() && + "double indirection not handled"); + addRegisterOpPiece(*Loc, Location.getReg(), + DV.getExpression().getPieceSize(), + DV.getExpression().getPieceOffset()); + i = 3; + } else + addRegisterOpPiece(*Loc, Location.getReg()); + } else + addRegisterOffset(*Loc, Location.getReg(), Location.getOffset()); + + for (; i < N; ++i) { + uint64_t Element = DV.getAddrElement(i); + if (Element == dwarf::DW_OP_plus) { + addUInt(*Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_plus_uconst); + addUInt(*Loc, dwarf::DW_FORM_udata, DV.getAddrElement(++i)); + + } else if (Element == dwarf::DW_OP_deref) { + if (!Location.isReg()) + addUInt(*Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_deref); + + } else if (Element == dwarf::DW_OP_piece) { + const unsigned SizeOfByte = 8; + unsigned PieceOffsetInBits = DV.getAddrElement(++i) * SizeOfByte; + unsigned PieceSizeInBits = DV.getAddrElement(++i) * SizeOfByte; + // Emit DW_OP_bit_piece Size Offset. + assert(PieceSizeInBits > 0 && "piece has zero size"); + addUInt(*Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_bit_piece); + addUInt(*Loc, dwarf::DW_FORM_udata, PieceSizeInBits); + addUInt(*Loc, dwarf::DW_FORM_udata, PieceOffsetInBits); + } else + llvm_unreachable("unknown DIBuilder Opcode"); + } + + // Now attach the location information to the DIE. + addBlock(Die, Attribute, Loc); +} + +/// Add a Dwarf loclistptr attribute data and value. +void DwarfCompileUnit::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); +} + +void DwarfCompileUnit::applyVariableAttributes(const DbgVariable &Var, + DIE &VariableDie) { + StringRef Name = Var.getName(); + if (!Name.empty()) + addString(VariableDie, dwarf::DW_AT_name, Name); + addSourceLine(VariableDie, Var.getVariable()); + addType(VariableDie, Var.getType()); + if (Var.isArtificial()) + addFlag(VariableDie, dwarf::DW_AT_artificial); +} + +/// Add a Dwarf expression attribute data and value. +void DwarfCompileUnit::addExpr(DIELoc &Die, dwarf::Form Form, + const MCExpr *Expr) { + DIEValue *Value = new (DIEValueAllocator) DIEExpr(Expr); + Die.addValue((dwarf::Attribute)0, Form, Value); +} + +void DwarfCompileUnit::applySubprogramAttributesToDefinition(DISubprogram SP, + DIE &SPDie) { + DISubprogram SPDecl = SP.getFunctionDeclaration(); + DIScope Context = resolve(SPDecl ? SPDecl.getContext() : SP.getContext()); + applySubprogramAttributes(SP, SPDie, includeMinimalInlineScopes()); + addGlobalName(SP.getName(), SPDie, Context); +} + +bool DwarfCompileUnit::isDwoUnit() const { + return DD->useSplitDwarf() && Skeleton; +} + +bool DwarfCompileUnit::includeMinimalInlineScopes() const { + return getCUNode().getEmissionKind() == DIBuilder::LineTablesOnly || + (DD->useSplitDwarf() && !Skeleton); +} +} // end llvm namespace diff --git a/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h b/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h new file mode 100644 index 0000000..e521f39 --- /dev/null +++ b/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h @@ -0,0 +1,250 @@ +//===-- llvm/CodeGen/DwarfCompileUnit.h - Dwarf Compile Unit ---*- C++ -*--===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains support for writing dwarf compile unit. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_CODEGEN_ASMPRINTER_DWARFCOMPILEUNIT_H +#define LLVM_LIB_CODEGEN_ASMPRINTER_DWARFCOMPILEUNIT_H + +#include "DwarfUnit.h" +#include "llvm/Support/Dwarf.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/IR/DebugInfo.h" + +namespace llvm { + +class AsmPrinter; +class DIE; +class DwarfDebug; +class DwarfFile; +class MCSymbol; +class LexicalScope; + +class DwarfCompileUnit : public DwarfUnit { + /// The attribute index of DW_AT_stmt_list in the compile unit DIE, avoiding + /// the need to search for it in applyStmtList. + unsigned stmtListIndex; + + /// Skeleton unit associated with this unit. + DwarfCompileUnit *Skeleton; + + /// A label at the start of the non-dwo section related to this unit. + MCSymbol *SectionSym; + + /// The start of the unit within its section. + MCSymbol *LabelBegin; + + /// GlobalNames - A map of globally visible named entities for this unit. + StringMap<const DIE *> GlobalNames; + + /// GlobalTypes - A map of globally visible types for this unit. + StringMap<const DIE *> GlobalTypes; + + // List of range lists for a given compile unit, separate from the ranges for + // the CU itself. + SmallVector<RangeSpanList, 1> CURangeLists; + + // List of ranges for a given compile unit. + SmallVector<RangeSpan, 2> CURanges; + + // The base address of this unit, if any. Used for relative references in + // ranges/locs. + const MCSymbol *BaseAddress; + + /// \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); + + bool isDwoUnit() const override; + + bool includeMinimalInlineScopes() const; + +public: + DwarfCompileUnit(unsigned UID, DICompileUnit Node, AsmPrinter *A, + DwarfDebug *DW, DwarfFile *DWU); + + DwarfCompileUnit *getSkeleton() const { + return Skeleton; + } + + void initStmtList(MCSymbol *DwarfLineSectionSym); + + /// Apply the DW_AT_stmt_list from this compile unit to the specified DIE. + void applyStmtList(DIE &D); + + /// getOrCreateGlobalVariableDIE - get or create global variable DIE. + DIE *getOrCreateGlobalVariableDIE(DIGlobalVariable GV); + + /// addLabelAddress - Add a dwarf label attribute data and value using + /// either DW_FORM_addr or DW_FORM_GNU_addr_index. + void addLabelAddress(DIE &Die, dwarf::Attribute Attribute, + const MCSymbol *Label); + + /// addLocalLabelAddress - Add a dwarf label attribute data and value using + /// DW_FORM_addr only. + void addLocalLabelAddress(DIE &Die, dwarf::Attribute Attribute, + const MCSymbol *Label); + + /// addSectionDelta - Add a label delta attribute data and value. + void addSectionDelta(DIE &Die, dwarf::Attribute Attribute, const MCSymbol *Hi, + const MCSymbol *Lo); + + DwarfCompileUnit &getCU() override { return *this; } + + unsigned getOrCreateSourceID(StringRef FileName, StringRef DirName) override; + + /// addRange - Add an address range to the list of ranges for this unit. + void addRange(RangeSpan Range); + + void attachLowHighPC(DIE &D, const MCSymbol *Begin, const MCSymbol *End); + + /// addSectionLabel - Add a Dwarf section label attribute data and value. + /// + void addSectionLabel(DIE &Die, dwarf::Attribute Attribute, + const MCSymbol *Label, const MCSymbol *Sec); + + /// \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(DISubprogram SP); + + void constructScopeDIE(LexicalScope *Scope, + SmallVectorImpl<std::unique_ptr<DIE>> &FinalChildren); + + /// \brief A helper function to construct a RangeSpanList for a given + /// lexical scope. + void addScopeRangeList(DIE &ScopeDIE, SmallVector<RangeSpan, 2> Range); + + void attachRangesOrLowHighPC(DIE &D, SmallVector<RangeSpan, 2> Ranges); + + void attachRangesOrLowHighPC(DIE &D, + const SmallVectorImpl<InsnRange> &Ranges); + /// \brief This scope represents inlined body of a function. Construct + /// DIE to represent this concrete inlined copy of the function. + std::unique_ptr<DIE> constructInlinedScopeDIE(LexicalScope *Scope); + + /// \brief Construct new DW_TAG_lexical_block for this scope and + /// attach DW_AT_low_pc/DW_AT_high_pc labels. + std::unique_ptr<DIE> constructLexicalScopeDIE(LexicalScope *Scope); + + /// constructVariableDIE - Construct a DIE for the given DbgVariable. + std::unique_ptr<DIE> constructVariableDIE(DbgVariable &DV, + bool Abstract = false); + + std::unique_ptr<DIE> constructVariableDIE(DbgVariable &DV, + const LexicalScope &Scope, + DIE *&ObjectPointer); + + /// A helper function to create children of a Scope DIE. + DIE *createScopeChildrenDIE(LexicalScope *Scope, + SmallVectorImpl<std::unique_ptr<DIE>> &Children, + unsigned *ChildScopeCount = nullptr); + + /// \brief Construct a DIE for this subprogram scope. + void constructSubprogramScopeDIE(LexicalScope *Scope); + + DIE *createAndAddScopeChildren(LexicalScope *Scope, DIE &ScopeDIE); + + void constructAbstractSubprogramScopeDIE(LexicalScope *Scope); + + /// \brief Construct import_module DIE. + std::unique_ptr<DIE> + constructImportedEntityDIE(const DIImportedEntity &Module); + + void finishSubprogramDefinition(DISubprogram SP); + + void collectDeadVariables(DISubprogram SP); + + /// Set the skeleton unit associated with this unit. + void setSkeleton(DwarfCompileUnit &Skel) { Skeleton = &Skel; } + + MCSymbol *getSectionSym() const { + assert(Section); + return SectionSym; + } + + /// Pass in the SectionSym even though we could recreate it in every compile + /// unit (type units will have actually distinct symbols once they're in + /// comdat sections). + void initSection(const MCSection *Section, MCSymbol *SectionSym) { + DwarfUnit::initSection(Section); + this->SectionSym = SectionSym; + + // Don't bother labeling the .dwo unit, as its offset isn't used. + if (!Skeleton) + LabelBegin = + Asm->GetTempSymbol(Section->getLabelBeginName(), getUniqueID()); + } + + unsigned getLength() { + return sizeof(uint32_t) + // Length field + getHeaderSize() + UnitDie.getSize(); + } + + void emitHeader(const MCSymbol *ASectionSym) const override; + + MCSymbol *getLabelBegin() const { + assert(Section); + return LabelBegin; + } + + /// Add a new global name to the compile unit. + void addGlobalName(StringRef Name, DIE &Die, DIScope Context) override; + + /// Add a new global type to the compile unit. + void addGlobalType(DIType Ty, const DIE &Die, DIScope Context) override; + + const StringMap<const DIE *> &getGlobalNames() const { return GlobalNames; } + const StringMap<const DIE *> &getGlobalTypes() const { return GlobalTypes; } + + /// Add DW_AT_location attribute for a DbgVariable based on provided + /// MachineLocation. + void addVariableAddress(const DbgVariable &DV, DIE &Die, + MachineLocation Location); + /// Add an address attribute to a die based on the location provided. + void addAddress(DIE &Die, dwarf::Attribute Attribute, + const MachineLocation &Location, bool Indirect = false); + + /// Start with the address based on the location provided, and generate the + /// DWARF information necessary to find the actual variable (navigating the + /// extra location information encoded in the type) based on the starting + /// location. Add the DWARF information to the die. + void addComplexAddress(const DbgVariable &DV, DIE &Die, + dwarf::Attribute Attribute, + const MachineLocation &Location); + + /// Add a Dwarf loclistptr attribute data and value. + void addLocationList(DIE &Die, dwarf::Attribute Attribute, unsigned Index); + void applyVariableAttributes(const DbgVariable &Var, DIE &VariableDie); + + /// Add a Dwarf expression attribute data and value. + void addExpr(DIELoc &Die, dwarf::Form Form, const MCExpr *Expr); + + void applySubprogramAttributesToDefinition(DISubprogram SP, DIE &SPDie); + + /// getRangeLists - Get the vector of range lists. + const SmallVectorImpl<RangeSpanList> &getRangeLists() const { + return (Skeleton ? Skeleton : this)->CURangeLists; + } + + /// getRanges - Get the list of ranges for this unit. + const SmallVectorImpl<RangeSpan> &getRanges() const { return CURanges; } + SmallVector<RangeSpan, 2> takeRanges() { return std::move(CURanges); } + + void setBaseAddress(const MCSymbol *Base) { BaseAddress = Base; } + const MCSymbol *getBaseAddress() const { return BaseAddress; } +}; + +} // end llvm namespace + +#endif diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp index 77860c0..230ea46 100644 --- a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -11,8 +11,10 @@ // //===----------------------------------------------------------------------===// -#include "ByteStreamer.h" #include "DwarfDebug.h" + +#include "ByteStreamer.h" +#include "DwarfCompileUnit.h" #include "DIE.h" #include "DIEHash.h" #include "DwarfUnit.h" @@ -36,6 +38,7 @@ #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/Dwarf.h" +#include "llvm/Support/Endian.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/FormattedStream.h" #include "llvm/Support/LEB128.h" @@ -47,6 +50,7 @@ #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetOptions.h" #include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Target/TargetSubtargetInfo.h" using namespace llvm; #define DEBUG_TYPE "dwarfdebug" @@ -149,7 +153,7 @@ DIType DbgVariable::getType() const { if (tag == dwarf::DW_TAG_pointer_type) subType = resolve(DIDerivedType(Ty).getTypeDerivedFrom()); - DIArray Elements = DICompositeType(subType).getTypeArray(); + DIArray Elements = DICompositeType(subType).getElements(); for (unsigned i = 0, N = Elements.getNumElements(); i < N; ++i) { DIDerivedType DT(Elements.getElement(i)); if (getName() == DT.getName()) @@ -165,10 +169,11 @@ static LLVM_CONSTEXPR DwarfAccelTable::Atom TypeAtoms[] = { DwarfAccelTable::Atom(dwarf::DW_ATOM_type_flags, dwarf::DW_FORM_data1)}; DwarfDebug::DwarfDebug(AsmPrinter *A, Module *M) - : Asm(A), MMI(Asm->MMI), FirstCU(nullptr), PrevLabel(nullptr), - GlobalRangeCount(0), InfoHolder(A, "info_string", DIEValueAllocator), + : Asm(A), MMI(Asm->MMI), PrevLabel(nullptr), GlobalRangeCount(0), + InfoHolder(A, *this, "info_string", DIEValueAllocator), UsedNonDefaultText(false), - SkeletonHolder(A, "skel_string", DIEValueAllocator), + SkeletonHolder(A, *this, "skel_string", DIEValueAllocator), + IsDarwin(Triple(A->getTargetTriple()).isOSDarwin()), AccelNames(DwarfAccelTable::Atom(dwarf::DW_ATOM_die_offset, dwarf::DW_FORM_data4)), AccelObjC(DwarfAccelTable::Atom(dwarf::DW_ATOM_die_offset, @@ -188,8 +193,6 @@ DwarfDebug::DwarfDebug(AsmPrinter *A, Module *M) // Turn on accelerator tables for Darwin by default, pubnames by // default for non-Darwin, and handle split dwarf. - bool IsDarwin = Triple(A->getTargetTriple()).isOSDarwin(); - if (DwarfAccelTables == Default) HasDwarfAccelTables = IsDarwin; else @@ -308,26 +311,6 @@ bool DwarfDebug::isSubprogramContext(const MDNode *Context) { return false; } -// 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, - DISubprogram SP) { - DIE *SPDie = SPCU.getOrCreateSubprogramDIE(SP); - - 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); - - // 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(SP, *SPDie); - - return *SPDie; -} - /// Check whether we should create a DIE for the given Scope, return true /// if we don't create a DIE (the corresponding DIE is null). bool DwarfDebug::isLexicalScopeDIENull(LexicalScope *Scope) { @@ -344,271 +327,30 @@ bool DwarfDebug::isLexicalScopeDIENull(LexicalScope *Scope) { // We don't create a DIE if we have a single Range and the end label // is null. - SmallVectorImpl<InsnRange>::const_iterator RI = Ranges.begin(); - MCSymbol *End = getLabelAfterInsn(RI->second); - return !End; -} - -static void addSectionLabel(AsmPrinter &Asm, DwarfUnit &U, DIE &D, - dwarf::Attribute A, const MCSymbol *L, - const MCSymbol *Sec) { - if (Asm.MAI->doesDwarfUseRelocationsAcrossSections()) - U.addSectionLabel(D, A, L); - else - U.addSectionDelta(D, A, L, Sec); -} - -void DwarfDebug::addScopeRangeList(DwarfCompileUnit &TheCU, DIE &ScopeDIE, - const SmallVectorImpl<InsnRange> &Range) { - // Emit offset in .debug_range as a relocatable label. emitDIE will handle - // emitting it appropriately. - MCSymbol *RangeSym = Asm->GetTempSymbol("debug_ranges", GlobalRangeCount++); - - // Under fission, ranges are specified by constant offsets relative to the - // CU's DW_AT_GNU_ranges_base. - if (useSplitDwarf()) - TheCU.addSectionDelta(ScopeDIE, dwarf::DW_AT_ranges, RangeSym, - DwarfDebugRangeSectionSym); - else - addSectionLabel(*Asm, TheCU, ScopeDIE, dwarf::DW_AT_ranges, RangeSym, - DwarfDebugRangeSectionSym); - - RangeSpanList List(RangeSym); - for (const InsnRange &R : Range) { - RangeSpan Span(getLabelBeforeInsn(R.first), getLabelAfterInsn(R.second)); - List.addRange(std::move(Span)); - } - - // Add the range list to the set of ranges to be emitted. - TheCU.addRangeList(std::move(List)); -} - -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. -std::unique_ptr<DIE> -DwarfDebug::constructLexicalScopeDIE(DwarfCompileUnit &TheCU, - LexicalScope *Scope) { - if (isLexicalScopeDIENull(Scope)) - return nullptr; - - auto ScopeDIE = make_unique<DIE>(dwarf::DW_TAG_lexical_block); - if (Scope->isAbstractScope()) - return ScopeDIE; - - attachRangesOrLowHighPC(TheCU, *ScopeDIE, Scope->getRanges()); - - return ScopeDIE; + return !getLabelAfterInsn(Ranges.front().second); } -// This scope represents inlined body of a function. Construct DIE to -// represent this concrete inlined copy of the function. -std::unique_ptr<DIE> -DwarfDebug::constructInlinedScopeDIE(DwarfCompileUnit &TheCU, - LexicalScope *Scope) { - assert(Scope->getScopeNode()); - DIScope DS(Scope->getScopeNode()); - DISubprogram InlinedSP = getDISubprogram(DS); - // 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."); - - auto ScopeDIE = make_unique<DIE>(dwarf::DW_TAG_inlined_subroutine); - TheCU.addDIEEntry(*ScopeDIE, dwarf::DW_AT_abstract_origin, *OriginDIE); - - 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()); - - // 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(InlinedSP, *ScopeDIE); - - return ScopeDIE; -} - -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) - 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()) { - Children.push_back( - make_unique<DIE>(dwarf::DW_TAG_unspecified_parameters)); - } - } - - // Collect lexical scope children first. - for (DbgVariable *DV : ScopeVariables.lookup(Scope)) - Children.push_back(constructVariableDIE(TheCU, *DV, *Scope, ObjectPointer)); - - for (LexicalScope *LS : Scope->getChildren()) - if (std::unique_ptr<DIE> Nested = constructScopeDIE(TheCU, LS)) - Children.push_back(std::move(Nested)); - return ObjectPointer; +template <typename Func> void forBothCUs(DwarfCompileUnit &CU, Func F) { + F(CU); + if (auto *SkelCU = CU.getSkeleton()) + F(*SkelCU); } -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) { +void DwarfDebug::constructAbstractSubprogramScopeDIE(LexicalScope *Scope) { assert(Scope && Scope->getScopeNode()); assert(Scope->isAbstractScope()); assert(!Scope->getInlinedAt()); - DISubprogram SP(Scope->getScopeNode()); + const MDNode *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.applySubprogramAttributesToDefinition(SP, *AbsDef); - - 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. -std::unique_ptr<DIE> DwarfDebug::constructScopeDIE(DwarfCompileUnit &TheCU, - LexicalScope *Scope) { - if (!Scope || !Scope->getScopeNode()) - return nullptr; - - DIScope DS(Scope->getScopeNode()); - - 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. - std::unique_ptr<DIE> ScopeDIE; - if (Scope->getParent() && DS.isSubprogram()) { - ScopeDIE = constructInlinedScopeDIE(TheCU, Scope); - 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 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. - 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, nullptr), - less_first()); - if (Children.empty() && Range.first == Range.second) - 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); - } - - // Add children - for (auto &I : Children) - ScopeDIE->addChild(std::move(I)); - - return ScopeDIE; + auto &CU = SPMap[SP]; + forBothCUs(*CU, [&](DwarfCompileUnit &CU) { + CU.constructAbstractSubprogramScopeDIE(Scope); + }); } void DwarfDebug::addGnuPubAttributes(DwarfUnit &U, DIE &D) const { @@ -629,6 +371,8 @@ DwarfCompileUnit &DwarfDebug::constructDwarfCompileUnit(DICompileUnit DIUnit) { DwarfCompileUnit &NewCU = *OwnedUnit; DIE &Die = NewCU.getUnitDie(); InfoHolder.addUnit(std::move(OwnedUnit)); + if (useSplitDwarf()) + NewCU.setSkeleton(constructSkeletonCU(NewCU)); // LTO with assembly output shares a single line table amongst multiple CUs. // To avoid the compilation directory being ambiguous, let the line table @@ -665,14 +409,10 @@ DwarfCompileUnit &DwarfDebug::constructDwarfCompileUnit(DICompileUnit DIUnit) { NewCU.addUInt(Die, dwarf::DW_AT_APPLE_major_runtime_vers, dwarf::DW_FORM_data1, RVer); - if (!FirstCU) - FirstCU = &NewCU; - - if (useSplitDwarf()) { + if (useSplitDwarf()) NewCU.initSection(Asm->getObjFileLowering().getDwarfInfoDWOSection(), DwarfInfoDWOSectionSym); - NewCU.setSkeleton(constructSkeletonCU(NewCU)); - } else + else NewCU.initSection(Asm->getObjFileLowering().getDwarfInfoSection(), DwarfInfoSectionSym); @@ -681,44 +421,12 @@ DwarfCompileUnit &DwarfDebug::constructDwarfCompileUnit(DICompileUnit DIUnit) { return NewCU; } -void DwarfDebug::constructImportedEntityDIE(DwarfCompileUnit &TheCU, - const MDNode *N) { +void DwarfDebug::constructAndAddImportedEntityDIE(DwarfCompileUnit &TheCU, + const MDNode *N) { DIImportedEntity Module(N); assert(Module.Verify()); if (DIE *D = TheCU.getOrCreateContextDIE(Module.getContext())) - constructImportedEntityDIE(TheCU, Module, *D); -} - -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, - const DIImportedEntity &Module, - DIE &Context) { - assert(Module.Verify() && - "Use one of the MDNode * overloads to handle invalid metadata"); - DIE &IMDie = TheCU.createAndAddDIE(Module.getTag(), Context, Module); - DIE *EntityDie; - DIDescriptor Entity = resolve(Module.getEntity()); - if (Entity.isNameSpace()) - EntityDie = TheCU.getOrCreateNameSpace(DINameSpace(Entity)); - else if (Entity.isSubprogram()) - EntityDie = TheCU.getOrCreateSubprogramDIE(DISubprogram(Entity)); - else if (Entity.isType()) - 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); - StringRef Name = Module.getName(); - if (!Name.empty()) - TheCU.addString(IMDie, dwarf::DW_AT_name, Name); + D->addChild(TheCU.constructImportedEntityDIE(Module)); } // Emit all Dwarf sections that should come prior to the content. Create @@ -732,8 +440,6 @@ void DwarfDebug::beginModule() { FunctionDIs = makeSubprogramMap(*M); - // If module has named metadata anchors then use them, otherwise scan the - // module using debug info finder to collect debug info. NamedMDNode *CU_Nodes = M->getNamedMetadata("llvm.dbg.cu"); if (!CU_Nodes) return; @@ -756,13 +462,18 @@ 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.getOrCreateGlobalVariableDIE(DIGlobalVariable(GVs.getElement(i))); DIArray SPs = CUNode.getSubprograms(); for (unsigned i = 0, e = SPs.getNumElements(); i != e; ++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)); + for (unsigned i = 0, e = EnumTypes.getNumElements(); i != e; ++i) { + DIType Ty(EnumTypes.getElement(i)); + // The enum types array by design contains pointers to + // MDNodes rather than DIRefs. Unique them here. + DIType UniqueTy(resolve(Ty.getRef())); + CU.getOrCreateTypeDIE(UniqueTy); + } DIArray RetainedTypes = CUNode.getRetainedTypes(); for (unsigned i = 0, e = RetainedTypes.getNumElements(); i != e; ++i) { DIType Ty(RetainedTypes.getElement(i)); @@ -774,7 +485,7 @@ void DwarfDebug::beginModule() { // Emit imported_modules last so that the relevant context is already // available. for (unsigned i = 0, e = ImportedEntities.getNumElements(); i != e; ++i) - constructImportedEntityDIE(CU, ImportedEntities.getElement(i)); + constructAndAddImportedEntityDIE(CU, ImportedEntities.getElement(i)); } // Tell MMI that we have debug info. @@ -787,9 +498,7 @@ void DwarfDebug::beginModule() { void DwarfDebug::finishVariableDefinitions() { for (const auto &Var : ConcreteVariables) { DIE *VariableDie = Var->getDIE(); - // FIXME: There shouldn't be any variables without DIEs. - if (!VariableDie) - continue; + assert(VariableDie); // FIXME: Consider the time-space tradeoff of just storing the unit pointer // in the ConcreteVariables list, rather than looking it up again here. // DIE::getUnit isn't simple - it walks parent pointers, etc. @@ -805,36 +514,10 @@ void DwarfDebug::finishVariableDefinitions() { } void DwarfDebug::finishSubprogramDefinitions() { - const Module *M = MMI->getModule(); - - 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->applySubprogramAttributesToDefinition(SP, *D); - } - } - } + for (const auto &P : SPMap) + forBothCUs(*P.second, [&](DwarfCompileUnit &CU) { + CU.finishSubprogramDefinition(DISubprogram(P.first)); + }); } @@ -854,26 +537,7 @@ void DwarfDebug::collectDeadVariables() { DISubprogram SP(Subprograms.getElement(i)); if (ProcessedSPNodes.count(SP) != 0) 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; - - 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)); - assert(DV.isVariable()); - DbgVariable NewVar(DV, this); - auto VariableDie = SPCU->constructVariableDIE(NewVar); - SPCU->applyVariableAttributes(NewVar, *VariableDie); - SPDIE->addChild(std::move(VariableDie)); - } + SPCU->collectDeadVariables(SP); } } } @@ -889,66 +553,52 @@ void DwarfDebug::finalizeModuleInfo() { // Handle anything that needs to be done on a per-unit basis after // all other generation. - for (const auto &TheU : getUnits()) { + for (const auto &P : CUMap) { + auto &TheCU = *P.second; // Emit DW_AT_containing_type attribute to connect types with their // vtable holding type. - TheU->constructContainingTypeDIEs(); + TheCU.constructContainingTypeDIEs(); // Add CU specific attributes if we need to add any. - if (TheU->getUnitDie().getTag() == dwarf::DW_TAG_compile_unit) { - // If we're splitting the dwarf out now that we've got the entire - // CU then add the dwo id to it. - DwarfCompileUnit *SkCU = - static_cast<DwarfCompileUnit *>(TheU->getSkeleton()); - if (useSplitDwarf()) { - // Emit a unique identifier for this CU. - uint64_t ID = DIEHash(Asm).computeCUSignature(TheU->getUnitDie()); - TheU->addUInt(TheU->getUnitDie(), dwarf::DW_AT_GNU_dwo_id, - dwarf::DW_FORM_data8, ID); - SkCU->addUInt(SkCU->getUnitDie(), dwarf::DW_AT_GNU_dwo_id, - dwarf::DW_FORM_data8, ID); - - // We don't keep track of which addresses are used in which CU so this - // is a bit pessimistic under LTO. - if (!AddrPool.isEmpty()) - addSectionLabel(*Asm, *SkCU, SkCU->getUnitDie(), - dwarf::DW_AT_GNU_addr_base, DwarfAddrSectionSym, - DwarfAddrSectionSym); - if (!TheU->getRangeLists().empty()) - addSectionLabel(*Asm, *SkCU, SkCU->getUnitDie(), - dwarf::DW_AT_GNU_ranges_base, - DwarfDebugRangeSectionSym, DwarfDebugRangeSectionSym); - } + // If we're splitting the dwarf out now that we've got the entire + // CU then add the dwo id to it. + auto *SkCU = TheCU.getSkeleton(); + if (useSplitDwarf()) { + // Emit a unique identifier for this CU. + uint64_t ID = DIEHash(Asm).computeCUSignature(TheCU.getUnitDie()); + TheCU.addUInt(TheCU.getUnitDie(), dwarf::DW_AT_GNU_dwo_id, + dwarf::DW_FORM_data8, ID); + SkCU->addUInt(SkCU->getUnitDie(), dwarf::DW_AT_GNU_dwo_id, + dwarf::DW_FORM_data8, ID); + + // We don't keep track of which addresses are used in which CU so this + // is a bit pessimistic under LTO. + if (!AddrPool.isEmpty()) + SkCU->addSectionLabel(SkCU->getUnitDie(), dwarf::DW_AT_GNU_addr_base, + DwarfAddrSectionSym, DwarfAddrSectionSym); + if (!SkCU->getRangeLists().empty()) + SkCU->addSectionLabel(SkCU->getUnitDie(), dwarf::DW_AT_GNU_ranges_base, + DwarfDebugRangeSectionSym, + DwarfDebugRangeSectionSym); + } - // If we have code split among multiple sections or non-contiguous - // ranges of code then emit a DW_AT_ranges attribute on the unit that will - // remain in the .o file, otherwise add a DW_AT_low_pc. - // FIXME: We should use ranges allow reordering of code ala - // .subsections_via_symbols in mach-o. This would mean turning on - // ranges for all subprogram DIEs for mach-o. - DwarfCompileUnit &U = - SkCU ? *SkCU : static_cast<DwarfCompileUnit &>(*TheU); - unsigned NumRanges = TheU->getRanges().size(); - if (NumRanges) { - if (NumRanges > 1) { - addSectionLabel(*Asm, U, U.getUnitDie(), dwarf::DW_AT_ranges, - Asm->GetTempSymbol("cu_ranges", U.getUniqueID()), - DwarfDebugRangeSectionSym); - - // A DW_AT_low_pc attribute may also be specified in combination with - // DW_AT_ranges to specify the default base address for use in - // location lists (see Section 2.6.2) and range lists (see Section - // 2.17.3). - U.addUInt(U.getUnitDie(), dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr, - 0); - } else { - RangeSpan &Range = TheU->getRanges().back(); - U.addLocalLabelAddress(U.getUnitDie(), dwarf::DW_AT_low_pc, - Range.getStart()); - U.addLabelDelta(U.getUnitDie(), dwarf::DW_AT_high_pc, Range.getEnd(), - Range.getStart()); - } - } + // If we have code split among multiple sections or non-contiguous + // ranges of code then emit a DW_AT_ranges attribute on the unit that will + // remain in the .o file, otherwise add a DW_AT_low_pc. + // FIXME: We should use ranges allow reordering of code ala + // .subsections_via_symbols in mach-o. This would mean turning on + // ranges for all subprogram DIEs for mach-o. + DwarfCompileUnit &U = SkCU ? *SkCU : TheCU; + if (unsigned NumRanges = TheCU.getRanges().size()) { + if (NumRanges > 1) + // A DW_AT_low_pc attribute may also be specified in combination with + // DW_AT_ranges to specify the default base address for use in + // location lists (see Section 2.6.2) and range lists (see Section + // 2.17.3). + U.addUInt(U.getUnitDie(), dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr, 0); + else + TheCU.setBaseAddress(TheCU.getRanges().front().getStart()); + U.attachRangesOrLowHighPC(U.getUnitDie(), TheCU.takeRanges()); } } @@ -1010,7 +660,10 @@ void DwarfDebug::endModule() { assert(CurFn == nullptr); assert(CurMI == nullptr); - if (!FirstCU) + // If we aren't actually generating debug info (check beginModule - + // conditionalized on !DisableDebugInfoPrinting and the presence of the + // llvm.dbg.cu metadata node) + if (!DwarfInfoSectionSym) return; // End any existing sections. @@ -1064,9 +717,6 @@ void DwarfDebug::endModule() { // clean up. SPMap.clear(); AbstractVariables.clear(); - - // Reset these for the next Module if we have one. - FirstCU = nullptr; } // Find abstract variable, if any, associated with Var. @@ -1092,8 +742,8 @@ DbgVariable *DwarfDebug::getExistingAbstractVariable(const DIVariable &DV) { void DwarfDebug::createAbstractVariable(const DIVariable &Var, LexicalScope *Scope) { - auto AbsDbgVariable = make_unique<DbgVariable>(Var, this); - addScopeVariable(Scope, AbsDbgVariable.get()); + auto AbsDbgVariable = make_unique<DbgVariable>(Var, DIExpression(), this); + InfoHolder.addScopeVariable(Scope, AbsDbgVariable.get()); AbstractVariables[Var] = std::move(AbsDbgVariable); } @@ -1117,55 +767,35 @@ DwarfDebug::ensureAbstractVariableIsCreatedIfScoped(const DIVariable &DV, createAbstractVariable(Cleansed, Scope); } -// If Var is a current function argument then add it to CurrentFnArguments list. -bool DwarfDebug::addCurrentFnArgument(DbgVariable *Var, LexicalScope *Scope) { - if (!LScopes.isCurrentFunctionScope(Scope)) - return false; - DIVariable DV = Var->getVariable(); - if (DV.getTag() != dwarf::DW_TAG_arg_variable) - return false; - unsigned ArgNo = DV.getArgNumber(); - if (ArgNo == 0) - return false; - - size_t Size = CurrentFnArguments.size(); - if (Size == 0) - CurrentFnArguments.resize(CurFn->getFunction()->arg_size()); - // llvm::Function argument size is not good indicator of how many - // arguments does the function have at source level. - if (ArgNo > Size) - CurrentFnArguments.resize(ArgNo * 2); - CurrentFnArguments[ArgNo - 1] = Var; - return true; -} - // Collect variable information from side table maintained by MMI. void DwarfDebug::collectVariableInfoFromMMITable( - SmallPtrSet<const MDNode *, 16> &Processed) { + SmallPtrSetImpl<const MDNode *> &Processed) { for (const auto &VI : MMI->getVariableDbgInfo()) { if (!VI.Var) continue; Processed.insert(VI.Var); - DIVariable DV(VI.Var); LexicalScope *Scope = LScopes.findLexicalScope(VI.Loc); // If variable scope is not found then skip this variable. if (!Scope) continue; + DIVariable DV(VI.Var); + DIExpression Expr(VI.Expr); ensureAbstractVariableIsCreatedIfScoped(DV, Scope->getScopeNode()); - ConcreteVariables.push_back(make_unique<DbgVariable>(DV, this)); + ConcreteVariables.push_back(make_unique<DbgVariable>(DV, Expr, this)); DbgVariable *RegVar = ConcreteVariables.back().get(); RegVar->setFrameIndex(VI.Slot); - addScopeVariable(Scope, RegVar); + InfoHolder.addScopeVariable(Scope, RegVar); } } // Get .debug_loc entry for the instruction range starting at MI. static DebugLocEntry::Value getDebugLocValue(const MachineInstr *MI) { + const MDNode *Expr = MI->getDebugExpression(); const MDNode *Var = MI->getDebugVariable(); - assert(MI->getNumOperands() == 3); + assert(MI->getNumOperands() == 4); if (MI->getOperand(0).isReg()) { MachineLocation MLoc; // If the second operand is an immediate, this is a @@ -1174,24 +804,138 @@ static DebugLocEntry::Value getDebugLocValue(const MachineInstr *MI) { MLoc.set(MI->getOperand(0).getReg()); else MLoc.set(MI->getOperand(0).getReg(), MI->getOperand(1).getImm()); - return DebugLocEntry::Value(Var, MLoc); + return DebugLocEntry::Value(Var, Expr, MLoc); } if (MI->getOperand(0).isImm()) - return DebugLocEntry::Value(Var, MI->getOperand(0).getImm()); + return DebugLocEntry::Value(Var, Expr, MI->getOperand(0).getImm()); if (MI->getOperand(0).isFPImm()) - return DebugLocEntry::Value(Var, MI->getOperand(0).getFPImm()); + return DebugLocEntry::Value(Var, Expr, MI->getOperand(0).getFPImm()); if (MI->getOperand(0).isCImm()) - return DebugLocEntry::Value(Var, MI->getOperand(0).getCImm()); + return DebugLocEntry::Value(Var, Expr, MI->getOperand(0).getCImm()); - llvm_unreachable("Unexpected 3 operand DBG_VALUE instruction!"); + llvm_unreachable("Unexpected 4-operand DBG_VALUE instruction!"); } -// Find variables for each lexical scope. +/// Determine whether two variable pieces overlap. +static bool piecesOverlap(DIExpression P1, DIExpression P2) { + if (!P1.isVariablePiece() || !P2.isVariablePiece()) + return true; + unsigned l1 = P1.getPieceOffset(); + unsigned l2 = P2.getPieceOffset(); + unsigned r1 = l1 + P1.getPieceSize(); + unsigned r2 = l2 + P2.getPieceSize(); + // True where [l1,r1[ and [r1,r2[ overlap. + return (l1 < r2) && (l2 < r1); +} + +/// Build the location list for all DBG_VALUEs in the function that +/// describe the same variable. If the ranges of several independent +/// pieces of the same variable overlap partially, split them up and +/// combine the ranges. The resulting DebugLocEntries are will have +/// strict monotonically increasing begin addresses and will never +/// overlap. +// +// Input: +// +// Ranges History [var, loc, piece ofs size] +// 0 | [x, (reg0, piece 0, 32)] +// 1 | | [x, (reg1, piece 32, 32)] <- IsPieceOfPrevEntry +// 2 | | ... +// 3 | [clobber reg0] +// 4 [x, (mem, piece 0, 64)] <- overlapping with both previous pieces of x. +// +// Output: +// +// [0-1] [x, (reg0, piece 0, 32)] +// [1-3] [x, (reg0, piece 0, 32), (reg1, piece 32, 32)] +// [3-4] [x, (reg1, piece 32, 32)] +// [4- ] [x, (mem, piece 0, 64)] void -DwarfDebug::collectVariableInfo(SmallPtrSet<const MDNode *, 16> &Processed) { - LexicalScope *FnScope = LScopes.getCurrentFunctionScope(); - DwarfCompileUnit *TheCU = SPMap.lookup(FnScope->getScopeNode()); +DwarfDebug::buildLocationList(SmallVectorImpl<DebugLocEntry> &DebugLoc, + const DbgValueHistoryMap::InstrRanges &Ranges) { + SmallVector<DebugLocEntry::Value, 4> OpenRanges; + + for (auto I = Ranges.begin(), E = Ranges.end(); I != E; ++I) { + const MachineInstr *Begin = I->first; + const MachineInstr *End = I->second; + assert(Begin->isDebugValue() && "Invalid History entry"); + + // Check if a variable is inaccessible in this range. + if (Begin->getNumOperands() > 1 && + Begin->getOperand(0).isReg() && !Begin->getOperand(0).getReg()) { + OpenRanges.clear(); + continue; + } + + // If this piece overlaps with any open ranges, truncate them. + DIExpression DIExpr = Begin->getDebugExpression(); + auto Last = std::remove_if(OpenRanges.begin(), OpenRanges.end(), + [&](DebugLocEntry::Value R) { + return piecesOverlap(DIExpr, R.getExpression()); + }); + OpenRanges.erase(Last, OpenRanges.end()); + + 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!"); + DEBUG(dbgs() << "DotDebugLoc: " << *Begin << "\n"); + + auto Value = getDebugLocValue(Begin); + DebugLocEntry Loc(StartLabel, EndLabel, Value); + bool couldMerge = false; + + // If this is a piece, it may belong to the current DebugLocEntry. + if (DIExpr.isVariablePiece()) { + // Add this value to the list of open ranges. + OpenRanges.push_back(Value); + + // Attempt to add the piece to the last entry. + if (!DebugLoc.empty()) + if (DebugLoc.back().MergeValues(Loc)) + couldMerge = true; + } + + if (!couldMerge) { + // Need to add a new DebugLocEntry. Add all values from still + // valid non-overlapping pieces. + if (OpenRanges.size()) + Loc.addValues(OpenRanges); + + DebugLoc.push_back(std::move(Loc)); + } + + // Attempt to coalesce the ranges of two otherwise identical + // DebugLocEntries. + auto CurEntry = DebugLoc.rbegin(); + auto PrevEntry = std::next(CurEntry); + if (PrevEntry != DebugLoc.rend() && PrevEntry->MergeRanges(*CurEntry)) + DebugLoc.pop_back(); + + DEBUG({ + dbgs() << CurEntry->getValues().size() << " Values:\n"; + for (auto Value : CurEntry->getValues()) { + Value.getVariable()->dump(); + Value.getExpression()->dump(); + } + dbgs() << "-----\n"; + }); + } +} + + +// Find variables for each lexical scope. +void +DwarfDebug::collectVariableInfo(DwarfCompileUnit &TheCU, DISubprogram SP, + SmallPtrSetImpl<const MDNode *> &Processed) { // Grab the variable info that was squirreled away in the MMI side-table. collectVariableInfoFromMMITable(Processed); @@ -1206,10 +950,7 @@ DwarfDebug::collectVariableInfo(SmallPtrSet<const MDNode *, 16> &Processed) { continue; 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()) { + if (MDNode *IA = DV.getInlinedAt()) { DebugLoc DL = DebugLoc::getFromDILocation(IA); Scope = LScopes.findInlinedScope(DebugLoc::get( DL.getLine(), DL.getCol(), DV.getContext(), IA)); @@ -1225,7 +966,7 @@ DwarfDebug::collectVariableInfo(SmallPtrSet<const MDNode *, 16> &Processed) { ensureAbstractVariableIsCreatedIfScoped(DV, Scope->getScopeNode()); ConcreteVariables.push_back(make_unique<DbgVariable>(MInsn, this)); DbgVariable *RegVar = ConcreteVariables.back().get(); - addScopeVariable(Scope, RegVar); + InfoHolder.addScopeVariable(Scope, RegVar); // Check if the first DBG_VALUE is valid for the rest of the function. if (Ranges.size() == 1 && Ranges.front().second == nullptr) @@ -1236,53 +977,26 @@ DwarfDebug::collectVariableInfo(SmallPtrSet<const MDNode *, 16> &Processed) { DotDebugLocEntries.resize(DotDebugLocEntries.size() + 1); DebugLocList &LocList = DotDebugLocEntries.back(); + LocList.CU = &TheCU; LocList.Label = Asm->GetTempSymbol("debug_loc", DotDebugLocEntries.size() - 1); - SmallVector<DebugLocEntry, 4> &DebugLoc = LocList.List; - for (auto I = Ranges.begin(), E = Ranges.end(); I != E; ++I) { - const MachineInstr *Begin = I->first; - const MachineInstr *End = I->second; - assert(Begin->isDebugValue() && "Invalid History entry"); - - // Check if a variable is unaccessible in this range. - if (Begin->getNumOperands() > 1 && Begin->getOperand(0).isReg() && - !Begin->getOperand(0).getReg()) - continue; - DEBUG(dbgs() << "DotDebugLoc Pair:\n" << "\t" << *Begin); - if (End != nullptr) - DEBUG(dbgs() << "\t" << *End); - else - DEBUG(dbgs() << "\tNULL\n"); - - 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!"); - DebugLocEntry Loc(StartLabel, EndLabel, getDebugLocValue(Begin), TheCU); - if (DebugLoc.empty() || !DebugLoc.back().Merge(Loc)) - DebugLoc.push_back(std::move(Loc)); - } + // Build the location list for this variable. + buildLocationList(LocList.List, Ranges); } // Collect info for variables that were optimized out. - DIArray Variables = DISubprogram(FnScope->getScopeNode()).getVariables(); + DIArray Variables = SP.getVariables(); for (unsigned i = 0, e = Variables.getNumElements(); i != e; ++i) { DIVariable DV(Variables.getElement(i)); assert(DV.isVariable()); - if (!Processed.insert(DV)) + if (!Processed.insert(DV).second) continue; if (LexicalScope *Scope = LScopes.findLexicalScope(DV.getContext())) { ensureAbstractVariableIsCreatedIfScoped(DV, Scope->getScopeNode()); - ConcreteVariables.push_back(make_unique<DbgVariable>(DV, this)); - addScopeVariable(Scope, ConcreteVariables.back().get()); + DIExpression NoExpr; + ConcreteVariables.push_back(make_unique<DbgVariable>(DV, NoExpr, this)); + InfoHolder.addScopeVariable(Scope, ConcreteVariables.back().get()); } } } @@ -1458,7 +1172,8 @@ void DwarfDebug::beginFunction(const MachineFunction *MF) { Asm->OutStreamer.EmitLabel(FunctionBeginSym); // Calculate history for local variables. - calculateDbgValueHistory(MF, Asm->TM.getRegisterInfo(), DbgValues); + calculateDbgValueHistory(MF, Asm->TM.getSubtargetImpl()->getRegisterInfo(), + DbgValues); // Request labels for the full history. for (const auto &I : DbgValues) { @@ -1468,10 +1183,24 @@ void DwarfDebug::beginFunction(const MachineFunction *MF) { // 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())) + DIVariable DIVar(Ranges.front().first->getDebugVariable()); + if (DIVar.isVariable() && DIVar.getTag() == dwarf::DW_TAG_arg_variable && + getDISubprogram(DIVar.getContext()).describes(MF->getFunction())) { LabelsBeforeInsn[Ranges.front().first] = FunctionBeginSym; + if (Ranges.front().first->getDebugExpression().isVariablePiece()) { + // Mark all non-overlapping initial pieces. + for (auto I = Ranges.begin(); I != Ranges.end(); ++I) { + DIExpression Piece = I->first->getDebugExpression(); + if (std::all_of(Ranges.begin(), I, + [&](DbgValueHistoryMap::InstrRange Pred) { + return !piecesOverlap(Piece, Pred.first->getDebugExpression()); + })) + LabelsBeforeInsn[I->first] = FunctionBeginSym; + else + break; + } + } + } for (const auto &Range : Ranges) { requestLabelBeforeInsn(Range.first); @@ -1497,56 +1226,16 @@ void DwarfDebug::beginFunction(const MachineFunction *MF) { } } -void DwarfDebug::addScopeVariable(LexicalScope *LS, DbgVariable *Var) { - if (addCurrentFnArgument(Var, LS)) - return; - SmallVectorImpl<DbgVariable *> &Vars = ScopeVariables[LS]; - DIVariable DV = Var->getVariable(); - // Variables with positive arg numbers are parameters. - if (unsigned ArgNum = DV.getArgNumber()) { - // Keep all parameters in order at the start of the variable list to ensure - // function types are correct (no out-of-order parameters) - // - // This could be improved by only doing it for optimized builds (unoptimized - // builds have the right order to begin with), searching from the back (this - // would catch the unoptimized case quickly), or doing a binary search - // rather than linear search. - SmallVectorImpl<DbgVariable *>::iterator I = Vars.begin(); - while (I != Vars.end()) { - unsigned CurNum = (*I)->getVariable().getArgNumber(); - // A local (non-parameter) variable has been found, insert immediately - // before it. - if (CurNum == 0) - break; - // A later indexed parameter has been found, insert immediately before it. - if (CurNum > ArgNum) - break; - ++I; - } - Vars.insert(I, Var); - return; - } - - Vars.push_back(Var); -} - // Gather and emit post-function debug information. 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) - CurFn = MF; - else - assert(CurFn == MF); - assert(CurFn != nullptr); + assert(CurFn == MF && + "endFunction should be called with the same function as beginFunction"); if (!MMI->hasDebugInfo() || LScopes.empty() || !FunctionDIs.count(MF->getFunction())) { // If we don't have a lexical scope for this function then there will // be a hole in the range information. Keep note of this by setting the // previously used section to nullptr. - PrevSection = nullptr; PrevCU = nullptr; CurFn = nullptr; return; @@ -1560,45 +1249,63 @@ void DwarfDebug::endFunction(const MachineFunction *MF) { // Set DwarfDwarfCompileUnitID in MCContext to default value. Asm->OutStreamer.getContext().setDwarfCompileUnitID(0); + LexicalScope *FnScope = LScopes.getCurrentFunctionScope(); + DISubprogram SP(FnScope->getScopeNode()); + DwarfCompileUnit &TheCU = *SPMap.lookup(SP); + SmallPtrSet<const MDNode *, 16> ProcessedVars; - collectVariableInfo(ProcessedVars); + collectVariableInfo(TheCU, SP, ProcessedVars); - LexicalScope *FnScope = LScopes.getCurrentFunctionScope(); - DwarfCompileUnit &TheCU = *SPMap.lookup(FnScope->getScopeNode()); + // Add the range of this function to the list of ranges for the CU. + TheCU.addRange(RangeSpan(FunctionBeginSym, FunctionEndSym)); + + // Under -gmlt, skip building the subprogram if there are no inlined + // subroutines inside it. + if (TheCU.getCUNode().getEmissionKind() == DIBuilder::LineTablesOnly && + LScopes.getAbstractScopesList().empty() && !IsDarwin) { + assert(InfoHolder.getScopeVariables().empty()); + assert(DbgValues.empty()); + // FIXME: This wouldn't be true in LTO with a -g (with inlining) CU followed + // by a -gmlt CU. Add a test and remove this assertion. + assert(AbstractVariables.empty()); + LabelsBeforeInsn.clear(); + LabelsAfterInsn.clear(); + PrevLabel = nullptr; + CurFn = nullptr; + return; + } +#ifndef NDEBUG + size_t NumAbstractScopes = LScopes.getAbstractScopesList().size(); +#endif // Construct abstract scopes. for (LexicalScope *AScope : LScopes.getAbstractScopesList()) { DISubprogram SP(AScope->getScopeNode()); - if (!SP.isSubprogram()) - continue; + assert(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)); assert(DV && DV.isVariable()); - if (!ProcessedVars.insert(DV)) + if (!ProcessedVars.insert(DV).second) continue; ensureAbstractVariableIsCreated(DV, DV.getContext()); + assert(LScopes.getAbstractScopesList().size() == NumAbstractScopes + && "ensureAbstractVariableIsCreated inserted abstract scopes"); } - constructAbstractSubprogramScopeDIE(TheCU, AScope); + constructAbstractSubprogramScopeDIE(AScope); } - DIE &CurFnDIE = constructSubprogramScopeDIE(TheCU, FnScope); - if (!CurFn->getTarget().Options.DisableFramePointerElim(*CurFn)) - TheCU.addFlag(CurFnDIE, dwarf::DW_AT_APPLE_omit_frame_ptr); - - // Add the range of this function to the list of ranges for the CU. - RangeSpan Span(FunctionBeginSym, FunctionEndSym); - TheCU.addRange(std::move(Span)); - PrevSection = Asm->getCurrentSection(); - PrevCU = &TheCU; + TheCU.constructSubprogramScopeDIE(FnScope); + if (auto *SkelCU = TheCU.getSkeleton()) + if (!LScopes.getAbstractScopesList().empty()) + SkelCU->constructSubprogramScopeDIE(FnScope); // Clear debug info // Ownership of DbgVariables is a bit subtle - ScopeVariables owns all the // DbgVariables except those that are also in AbstractVariables (since they // can be used cross-function) - ScopeVariables.clear(); - CurrentFnArguments.clear(); + InfoHolder.getScopeVariables().clear(); DbgValues.clear(); LabelsBeforeInsn.clear(); LabelsAfterInsn.clear(); @@ -1618,8 +1325,8 @@ void DwarfDebug::recordSourceLine(unsigned Line, unsigned Col, const MDNode *S, assert(Scope.isScope()); Fn = Scope.getFilename(); Dir = Scope.getDirectory(); - if (Scope.isLexicalBlock()) - Discriminator = DILexicalBlock(S).getDiscriminator(); + if (Scope.isLexicalBlockFile()) + Discriminator = DILexicalBlockFile(S).getDiscriminator(); unsigned CUID = Asm->OutStreamer.getContext().getDwarfCompileUnitID(); Src = static_cast<DwarfCompileUnit &>(*InfoHolder.getUnits()[CUID]) @@ -1640,9 +1347,12 @@ void DwarfDebug::emitSectionLabels() { // Dwarf sections base addresses. DwarfInfoSectionSym = emitSectionSym(Asm, TLOF.getDwarfInfoSection(), "section_info"); - if (useSplitDwarf()) + if (useSplitDwarf()) { DwarfInfoDWOSectionSym = emitSectionSym(Asm, TLOF.getDwarfInfoDWOSection(), "section_info_dwo"); + DwarfTypesDWOSectionSym = + emitSectionSym(Asm, TLOF.getDwarfTypesDWOSection(), "section_types_dwo"); + } DwarfAbbrevSectionSym = emitSectionSym(Asm, TLOF.getDwarfAbbrevSection(), "section_abbrev"); if (useSplitDwarf()) @@ -1726,7 +1436,7 @@ void DwarfDebug::emitDIE(DIE &Die) { void DwarfDebug::emitDebugInfo() { DwarfFile &Holder = useSplitDwarf() ? SkeletonHolder : InfoHolder; - Holder.emitUnits(this, DwarfAbbrevSectionSym); + Holder.emitUnits(DwarfAbbrevSectionSym); } // Emit the abbreviation section. @@ -1760,54 +1470,41 @@ void DwarfDebug::emitEndOfLineMatrix(unsigned SectionEnd) { Asm->EmitInt8(1); } -// Emit visible names into a hashed accelerator table section. -void DwarfDebug::emitAccelNames() { - AccelNames.FinalizeTable(Asm, "Names"); - Asm->OutStreamer.SwitchSection( - Asm->getObjFileLowering().getDwarfAccelNamesSection()); - MCSymbol *SectionBegin = Asm->GetTempSymbol("names_begin"); +void DwarfDebug::emitAccel(DwarfAccelTable &Accel, const MCSection *Section, + StringRef TableName, StringRef SymName) { + Accel.FinalizeTable(Asm, TableName); + Asm->OutStreamer.SwitchSection(Section); + auto *SectionBegin = Asm->GetTempSymbol(SymName); Asm->OutStreamer.EmitLabel(SectionBegin); // Emit the full data. - AccelNames.Emit(Asm, SectionBegin, &InfoHolder); + Accel.Emit(Asm, SectionBegin, this, DwarfStrSectionSym); +} + +// Emit visible names into a hashed accelerator table section. +void DwarfDebug::emitAccelNames() { + emitAccel(AccelNames, Asm->getObjFileLowering().getDwarfAccelNamesSection(), + "Names", "names_begin"); } // Emit objective C classes and categories into a hashed accelerator table // section. void DwarfDebug::emitAccelObjC() { - AccelObjC.FinalizeTable(Asm, "ObjC"); - Asm->OutStreamer.SwitchSection( - Asm->getObjFileLowering().getDwarfAccelObjCSection()); - MCSymbol *SectionBegin = Asm->GetTempSymbol("objc_begin"); - Asm->OutStreamer.EmitLabel(SectionBegin); - - // Emit the full data. - AccelObjC.Emit(Asm, SectionBegin, &InfoHolder); + emitAccel(AccelObjC, Asm->getObjFileLowering().getDwarfAccelObjCSection(), + "ObjC", "objc_begin"); } // Emit namespace dies into a hashed accelerator table. void DwarfDebug::emitAccelNamespaces() { - AccelNamespace.FinalizeTable(Asm, "namespac"); - Asm->OutStreamer.SwitchSection( - Asm->getObjFileLowering().getDwarfAccelNamespaceSection()); - MCSymbol *SectionBegin = Asm->GetTempSymbol("namespac_begin"); - Asm->OutStreamer.EmitLabel(SectionBegin); - - // Emit the full data. - AccelNamespace.Emit(Asm, SectionBegin, &InfoHolder); + emitAccel(AccelNamespace, + Asm->getObjFileLowering().getDwarfAccelNamespaceSection(), + "namespac", "namespac_begin"); } // Emit type dies into a hashed accelerator table. void DwarfDebug::emitAccelTypes() { - - AccelTypes.FinalizeTable(Asm, "types"); - Asm->OutStreamer.SwitchSection( - Asm->getObjFileLowering().getDwarfAccelTypesSection()); - MCSymbol *SectionBegin = Asm->GetTempSymbol("types_begin"); - Asm->OutStreamer.EmitLabel(SectionBegin); - - // Emit the full data. - AccelTypes.Emit(Asm, SectionBegin, &InfoHolder); + emitAccel(AccelTypes, Asm->getObjFileLowering().getDwarfAccelTypesSection(), + "types", "types_begin"); } // Public name handling. @@ -1874,12 +1571,13 @@ void DwarfDebug::emitDebugPubNames(bool GnuStyle) { GnuStyle ? Asm->getObjFileLowering().getDwarfGnuPubNamesSection() : Asm->getObjFileLowering().getDwarfPubNamesSection(); - emitDebugPubSection(GnuStyle, PSec, "Names", &DwarfUnit::getGlobalNames); + emitDebugPubSection(GnuStyle, PSec, "Names", + &DwarfCompileUnit::getGlobalNames); } void DwarfDebug::emitDebugPubSection( bool GnuStyle, const MCSection *PSec, StringRef Name, - const StringMap<const DIE *> &(DwarfUnit::*Accessor)() const) { + const StringMap<const DIE *> &(DwarfCompileUnit::*Accessor)() const) { for (const auto &NU : CUMap) { DwarfCompileUnit *TheU = NU.second; @@ -1888,7 +1586,7 @@ void DwarfDebug::emitDebugPubSection( if (Globals.empty()) continue; - if (auto Skeleton = static_cast<DwarfCompileUnit *>(TheU->getSkeleton())) + if (auto *Skeleton = TheU->getSkeleton()) TheU = Skeleton; unsigned ID = TheU->getUniqueID(); @@ -1910,7 +1608,7 @@ void DwarfDebug::emitDebugPubSection( Asm->EmitSectionOffset(TheU->getLabelBegin(), TheU->getSectionSym()); Asm->OutStreamer.AddComment("Compilation Unit Length"); - Asm->EmitLabelDifference(TheU->getLabelEnd(), TheU->getLabelBegin(), 4); + Asm->EmitInt32(TheU->getLength()); // Emit the pubnames for this compilation unit. for (const auto &GI : Globals) { @@ -1943,7 +1641,8 @@ void DwarfDebug::emitDebugPubTypes(bool GnuStyle) { GnuStyle ? Asm->getObjFileLowering().getDwarfGnuPubTypesSection() : Asm->getObjFileLowering().getDwarfPubTypesSection(); - emitDebugPubSection(GnuStyle, PSec, "Types", &DwarfUnit::getGlobalTypes); + emitDebugPubSection(GnuStyle, PSec, "Types", + &DwarfCompileUnit::getGlobalTypes); } // Emit visible names into a debug str section. @@ -1952,12 +1651,67 @@ void DwarfDebug::emitDebugStr() { Holder.emitStrings(Asm->getObjFileLowering().getDwarfStrSection()); } +/// Emits an optimal (=sorted) sequence of DW_OP_pieces. +void DwarfDebug::emitLocPieces(ByteStreamer &Streamer, + const DITypeIdentifierMap &Map, + ArrayRef<DebugLocEntry::Value> Values) { + assert(std::all_of(Values.begin(), Values.end(), [](DebugLocEntry::Value P) { + return P.isVariablePiece(); + }) && "all values are expected to be pieces"); + assert(std::is_sorted(Values.begin(), Values.end()) && + "pieces are expected to be sorted"); + + unsigned Offset = 0; + for (auto Piece : Values) { + DIExpression Expr = Piece.getExpression(); + unsigned PieceOffset = Expr.getPieceOffset(); + unsigned PieceSize = Expr.getPieceSize(); + assert(Offset <= PieceOffset && "overlapping or duplicate pieces"); + if (Offset < PieceOffset) { + // The DWARF spec seriously mandates pieces with no locations for gaps. + Asm->EmitDwarfOpPiece(Streamer, (PieceOffset-Offset)*8); + Offset += PieceOffset-Offset; + } + + Offset += PieceSize; + + const unsigned SizeOfByte = 8; +#ifndef NDEBUG + DIVariable Var = Piece.getVariable(); + assert(!Var.isIndirect() && "indirect address for piece"); + unsigned VarSize = Var.getSizeInBits(Map); + assert(PieceSize+PieceOffset <= VarSize/SizeOfByte + && "piece is larger than or outside of variable"); + assert(PieceSize*SizeOfByte != VarSize + && "piece covers entire variable"); +#endif + if (Piece.isLocation() && Piece.getLoc().isReg()) + Asm->EmitDwarfRegOpPiece(Streamer, + Piece.getLoc(), + PieceSize*SizeOfByte); + else { + emitDebugLocValue(Streamer, Piece); + Asm->EmitDwarfOpPiece(Streamer, PieceSize*SizeOfByte); + } + } +} + + void DwarfDebug::emitDebugLocEntry(ByteStreamer &Streamer, const DebugLocEntry &Entry) { - 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.isVariablePiece()) + // Emit all pieces that belong to the same variable and range. + return emitLocPieces(Streamer, TypeIdentifierMap, Entry.getValues()); + + assert(Entry.getValues().size() == 1 && "only pieces may have >1 value"); + emitDebugLocValue(Streamer, Value); +} + +void DwarfDebug::emitDebugLocValue(ByteStreamer &Streamer, + const DebugLocEntry::Value &Value) { + DIVariable DV = Value.getVariable(); + // Regular entry. if (Value.isInt()) { DIBasicType BTy(resolve(DV.getType())); if (BTy.Verify() && (BTy.getEncoding() == dwarf::DW_ATE_signed || @@ -1970,24 +1724,25 @@ void DwarfDebug::emitDebugLocEntry(ByteStreamer &Streamer, } } else if (Value.isLocation()) { MachineLocation Loc = Value.getLoc(); - if (!DV.hasComplexAddress()) + DIExpression Expr = Value.getExpression(); + if (!Expr) // Regular entry. Asm->EmitDwarfRegOp(Streamer, Loc, DV.isIndirect()); else { // Complex address entry. - unsigned N = DV.getNumAddrElements(); + unsigned N = Expr.getNumElements(); unsigned i = 0; - if (N >= 2 && DV.getAddrElement(0) == DIBuilder::OpPlus) { + if (N >= 2 && Expr.getElement(0) == dwarf::DW_OP_plus) { if (Loc.getOffset()) { i = 2; Asm->EmitDwarfRegOp(Streamer, Loc, DV.isIndirect()); Streamer.EmitInt8(dwarf::DW_OP_deref, "DW_OP_deref"); Streamer.EmitInt8(dwarf::DW_OP_plus_uconst, "DW_OP_plus_uconst"); - Streamer.EmitSLEB128(DV.getAddrElement(1)); + Streamer.EmitSLEB128(Expr.getElement(1)); } else { // If first address element is OpPlus then emit // DW_OP_breg + Offset instead of DW_OP_reg + Offset. - MachineLocation TLoc(Loc.getReg(), DV.getAddrElement(1)); + MachineLocation TLoc(Loc.getReg(), Expr.getElement(1)); Asm->EmitDwarfRegOp(Streamer, TLoc, DV.isIndirect()); i = 2; } @@ -1997,13 +1752,16 @@ void DwarfDebug::emitDebugLocEntry(ByteStreamer &Streamer, // Emit remaining complex address elements. for (; i < N; ++i) { - uint64_t Element = DV.getAddrElement(i); - if (Element == DIBuilder::OpPlus) { + uint64_t Element = Expr.getElement(i); + if (Element == dwarf::DW_OP_plus) { Streamer.EmitInt8(dwarf::DW_OP_plus_uconst, "DW_OP_plus_uconst"); - Streamer.EmitULEB128(DV.getAddrElement(++i)); - } else if (Element == DIBuilder::OpDeref) { + Streamer.EmitULEB128(Expr.getElement(++i)); + } else if (Element == dwarf::DW_OP_deref) { if (!Loc.isReg()) Streamer.EmitInt8(dwarf::DW_OP_deref, "DW_OP_deref"); + } else if (Element == dwarf::DW_OP_piece) { + i += 3; + // handled in emitDebugLocEntry. } else llvm_unreachable("unknown Opcode found in complex address"); } @@ -2035,14 +1793,12 @@ void DwarfDebug::emitDebugLoc() { unsigned char Size = Asm->getDataLayout().getPointerSize(); for (const auto &DebugLoc : DotDebugLocEntries) { Asm->OutStreamer.EmitLabel(DebugLoc.Label); + const DwarfCompileUnit *CU = DebugLoc.CU; for (const auto &Entry : DebugLoc.List) { // Set up the range. This range is relative to the entry point of the // compile unit. This is a hard coded 0 for low_pc when we're emitting // ranges, or the DW_AT_low_pc on the compile unit otherwise. - const DwarfCompileUnit *CU = Entry.getCU(); - if (CU->getRanges().size() == 1) { - // Grab the begin symbol from the first range as our base. - const MCSymbol *Base = CU->getRanges()[0].getStart(); + if (auto *Base = CU->getBaseAddress()) { Asm->EmitLabelDifference(Entry.getBeginSym(), Base, Size); Asm->EmitLabelDifference(Entry.getEndSym(), Base, Size); } else { @@ -2172,6 +1928,10 @@ void DwarfDebug::emitDebugARanges() { for (DwarfCompileUnit *CU : CUs) { std::vector<ArangeSpan> &List = Spans[CU]; + // Describe the skeleton CU's offset and length, not the dwo file's. + if (auto *Skel = CU->getSkeleton()) + CU = Skel; + // Emit size of content not including length itself. unsigned ContentSize = sizeof(int16_t) + // DWARF ARange version number @@ -2194,7 +1954,7 @@ void DwarfDebug::emitDebugARanges() { Asm->OutStreamer.AddComment("DWARF Arange version number"); Asm->EmitInt16(dwarf::DW_ARANGES_VERSION); Asm->OutStreamer.AddComment("Offset Into Debug Info Section"); - Asm->EmitSectionOffset(CU->getLocalLabelBegin(), CU->getLocalSectionSym()); + Asm->EmitSectionOffset(CU->getLabelBegin(), CU->getSectionSym()); Asm->OutStreamer.AddComment("Address Size (in bytes)"); Asm->EmitInt8(PtrSize); Asm->OutStreamer.AddComment("Segment Size (in bytes)"); @@ -2238,6 +1998,9 @@ void DwarfDebug::emitDebugRanges() { for (const auto &I : CUMap) { DwarfCompileUnit *TheCU = I.second; + if (auto *Skel = TheCU->getSkeleton()) + TheCU = Skel; + // Iterate over the misc ranges for the compile units in the module. for (const RangeSpanList &List : TheCU->getRangeLists()) { // Emit our symbol so we can find the beginning of the range. @@ -2248,9 +2011,7 @@ void DwarfDebug::emitDebugRanges() { const MCSymbol *End = Range.getEnd(); assert(Begin && "Range without a begin symbol?"); assert(End && "Range without an end symbol?"); - if (TheCU->getRanges().size() == 1) { - // Grab the begin symbol from the first range as our base. - const MCSymbol *Base = TheCU->getRanges()[0].getStart(); + if (auto *Base = TheCU->getBaseAddress()) { Asm->EmitLabelDifference(Begin, Base, Size); Asm->EmitLabelDifference(End, Base, Size); } else { @@ -2263,23 +2024,6 @@ void DwarfDebug::emitDebugRanges() { Asm->OutStreamer.EmitIntValue(0, Size); Asm->OutStreamer.EmitIntValue(0, Size); } - - // Now emit a range for the CU itself. - if (TheCU->getRanges().size() > 1) { - Asm->OutStreamer.EmitLabel( - Asm->GetTempSymbol("cu_ranges", TheCU->getUniqueID())); - for (const RangeSpan &Range : TheCU->getRanges()) { - const MCSymbol *Begin = Range.getStart(); - const MCSymbol *End = Range.getEnd(); - assert(Begin && "Range without a begin symbol?"); - assert(End && "Range without an end symbol?"); - Asm->OutStreamer.EmitSymbolValue(Begin, Size); - Asm->OutStreamer.EmitSymbolValue(End, Size); - } - // And terminate the list with two 0 values. - Asm->OutStreamer.EmitIntValue(0, Size); - Asm->OutStreamer.EmitIntValue(0, Size); - } } } @@ -2287,11 +2031,11 @@ void DwarfDebug::emitDebugRanges() { 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()); + NewU->addString(Die, dwarf::DW_AT_GNU_dwo_name, + U.getCUNode().getSplitDebugFilename()); if (!CompilationDir.empty()) - NewU->addLocalString(Die, dwarf::DW_AT_comp_dir, CompilationDir); + NewU->addString(Die, dwarf::DW_AT_comp_dir, CompilationDir); addGnuPubAttributes(*NewU, Die); @@ -2316,31 +2060,13 @@ DwarfCompileUnit &DwarfDebug::constructSkeletonCU(const DwarfCompileUnit &CU) { 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) { - DwarfCompileUnit &CU = static_cast<DwarfCompileUnit &>( - *SkeletonHolder.getUnits()[TU.getCU().getUniqueID()]); - - 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, NewTU.getUnitDie(), std::move(OwnedUnit)); - return NewTU; -} - // Emit the .debug_info.dwo section for separated dwarf. This contains the // compile units that would normally be in debug_info. void DwarfDebug::emitDebugInfoDWO() { assert(useSplitDwarf() && "No split dwarf debug info?"); // 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(/* AbbrevSymbol */ nullptr); } // Emit the .debug_abbrev.dwo section for separated dwarf. This contains the @@ -2364,9 +2090,8 @@ void DwarfDebug::emitDebugStrDWO() { assert(useSplitDwarf() && "No split dwarf?"); const MCSection *OffSec = Asm->getObjFileLowering().getDwarfStrOffDWOSection(); - const MCSymbol *StrSym = DwarfStrSectionSym; InfoHolder.emitStrings(Asm->getObjFileLowering().getDwarfStrDWOSection(), - OffSec, StrSym); + OffSec); } MCDwarfDwoLineTable *DwarfDebug::getDwoLineTable(const DwarfCompileUnit &CU) { @@ -2406,9 +2131,9 @@ void DwarfDebug::addDwarfTypeUnitType(DwarfCompileUnit &CU, bool TopLevelType = TypeUnitsUnderConstruction.empty(); AddrPool.resetUsedFlag(); - auto OwnedUnit = - make_unique<DwarfTypeUnit>(InfoHolder.getUnits().size(), CU, Asm, this, - &InfoHolder, getDwoLineTable(CU)); + auto OwnedUnit = make_unique<DwarfTypeUnit>( + InfoHolder.getUnits().size() + TypeUnitsUnderConstruction.size(), CU, Asm, + this, &InfoHolder, getDwoLineTable(CU)); DwarfTypeUnit &NewTU = *OwnedUnit; DIE &UnitDie = NewTU.getUnitDie(); TU = &NewTU; @@ -2421,15 +2146,13 @@ void DwarfDebug::addDwarfTypeUnitType(DwarfCompileUnit &CU, uint64_t Signature = makeTypeSignature(Identifier); NewTU.setTypeSignature(Signature); - if (!useSplitDwarf()) + if (useSplitDwarf()) + NewTU.initSection(Asm->getObjFileLowering().getDwarfTypesDWOSection()); + else { 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)); + NewTU.initSection( + Asm->getObjFileLowering().getDwarfTypesSection(Signature)); + } NewTU.setType(NewTU.createTypeDIE(CTy)); @@ -2457,29 +2180,12 @@ void DwarfDebug::addDwarfTypeUnitType(DwarfCompileUnit &CU, // 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)); + for (auto &TU : TypeUnitsToAdd) InfoHolder.addUnit(std::move(TU.first)); - } } CU.addDIETypeSignature(RefDie, NewTU); } -void DwarfDebug::attachLowHighPC(DwarfCompileUnit &Unit, DIE &D, - MCSymbol *Begin, MCSymbol *End) { - 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); - else - 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 diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.h b/lib/CodeGen/AsmPrinter/DwarfDebug.h index ffe4843..48c2809 100644 --- a/lib/CodeGen/AsmPrinter/DwarfDebug.h +++ b/lib/CodeGen/AsmPrinter/DwarfDebug.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef CODEGEN_ASMPRINTER_DWARFDEBUG_H__ -#define CODEGEN_ASMPRINTER_DWARFDEBUG_H__ +#ifndef LLVM_LIB_CODEGEN_ASMPRINTER_DWARFDEBUG_H +#define LLVM_LIB_CODEGEN_ASMPRINTER_DWARFDEBUG_H #include "DwarfFile.h" #include "AsmPrinterHandler.h" @@ -70,6 +70,7 @@ public: /// \brief This class is used to track local variable information. class DbgVariable { DIVariable Var; // Variable Descriptor. + DIExpression Expr; // Complex address location expression. DIE *TheDIE; // Variable DIE. unsigned DotDebugLocOffset; // Offset in DotDebugLocEntries. const MachineInstr *MInsn; // DBG_VALUE instruction of the variable. @@ -78,18 +79,22 @@ class DbgVariable { public: /// Construct a DbgVariable from a DIVariable. - DbgVariable(DIVariable V, DwarfDebug *DD) - : Var(V), TheDIE(nullptr), DotDebugLocOffset(~0U), MInsn(nullptr), - FrameIndex(~0), DD(DD) {} + DbgVariable(DIVariable V, DIExpression E, DwarfDebug *DD) + : Var(V), Expr(E), TheDIE(nullptr), DotDebugLocOffset(~0U), + MInsn(nullptr), FrameIndex(~0), DD(DD) { + assert(Var.Verify() && Expr.Verify()); + } /// Construct a DbgVariable from a DEBUG_VALUE. /// AbstractVar may be NULL. DbgVariable(const MachineInstr *DbgValue, DwarfDebug *DD) - : Var(DbgValue->getDebugVariable()), TheDIE(nullptr), - DotDebugLocOffset(~0U), MInsn(DbgValue), FrameIndex(~0), DD(DD) {} + : Var(DbgValue->getDebugVariable()), Expr(DbgValue->getDebugExpression()), + TheDIE(nullptr), DotDebugLocOffset(~0U), MInsn(DbgValue), + FrameIndex(~0), DD(DD) {} // Accessors. DIVariable getVariable() const { return Var; } + DIExpression getExpression() const { return Expr; } void setDIE(DIE &D) { TheDIE = &D; } DIE *getDIE() const { return TheDIE; } void setDotDebugLocOffset(unsigned O) { DotDebugLocOffset = O; } @@ -124,14 +129,14 @@ public: bool variableHasComplexAddress() const { assert(Var.isVariable() && "Invalid complex DbgVariable!"); - return Var.hasComplexAddress(); + return Expr.getNumElements() > 0; } bool isBlockByrefVariable() const; unsigned getNumAddrElements() const { assert(Var.isVariable() && "Invalid complex DbgVariable!"); - return Var.getNumAddrElements(); + return Expr.getNumElements(); } - uint64_t getAddrElement(unsigned i) const { return Var.getAddrElement(i); } + uint64_t getAddrElement(unsigned i) const { return Expr.getElement(i); } DIType getType() const; private: @@ -159,26 +164,15 @@ class DwarfDebug : public AsmPrinterHandler { // All DIEValues are allocated through this allocator. BumpPtrAllocator DIEValueAllocator; - // Handle to the compile unit used for the inline extension handling, - // this is just so that the DIEValue allocator has a place to store - // the particular elements. - // FIXME: Store these off of DwarfDebug instead? - DwarfCompileUnit *FirstCU; - // Maps MDNode with its corresponding DwarfCompileUnit. MapVector<const MDNode *, DwarfCompileUnit *> CUMap; // Maps subprogram MDNode with its corresponding DwarfCompileUnit. - DenseMap<const MDNode *, DwarfCompileUnit *> SPMap; + MapVector<const MDNode *, DwarfCompileUnit *> SPMap; // Maps a CU DIE with its corresponding DwarfCompileUnit. DenseMap<const DIE *, DwarfCompileUnit *> CUDieMap; - /// Maps MDNodes for type system with the corresponding DIEs. These DIEs can - /// be shared across CUs, that is why we keep the map here instead - /// of in DwarfCompileUnit. - DenseMap<const MDNode *, DIE *> MDTypeNodeToDieMap; - // List of all labels used in aranges generation. std::vector<SymbolCU> ArangeLabels; @@ -189,19 +183,8 @@ class DwarfDebug : public AsmPrinterHandler { typedef DenseMap<const MCSection *, SmallVector<SymbolCU, 8> > SectionMapType; SectionMapType SectionMap; - // List of arguments for current function. - SmallVector<DbgVariable *, 8> CurrentFnArguments; - LexicalScopes LScopes; - // Collection of abstract subprogram DIEs. - DenseMap<const MDNode *, DIE *> AbstractSPDies; - - // Collection of dbg variables of a scope. - typedef DenseMap<LexicalScope *, SmallVector<DbgVariable *, 8> > - ScopeVariablesMap; - ScopeVariablesMap ScopeVariables; - // Collection of abstract variables. DenseMap<const MDNode *, std::unique_ptr<DbgVariable>> AbstractVariables; SmallVector<std::unique_ptr<DbgVariable>, 64> ConcreteVariables; @@ -210,10 +193,6 @@ class DwarfDebug : public AsmPrinterHandler { // can refer to them in spite of insertions into this list. SmallVector<DebugLocList, 4> DotDebugLocEntries; - // Collection of subprogram DIEs that are marked (at the end of the module) - // as DW_AT_inline. - SmallPtrSet<DIE *, 4> InlinedSubprogramDIEs; - // This is a collection of subprogram MDNodes that are processed to // create DIEs. SmallPtrSet<const MDNode *, 16> ProcessedSPNodes; @@ -243,10 +222,6 @@ class DwarfDebug : public AsmPrinterHandler { // If nonnull, stores the current machine instruction we're processing. const MachineInstr *CurMI; - // If nonnull, stores the section that the previous function was allocated to - // emitting. - const MCSection *PrevSection; - // If nonnull, stores the CU in which the previous subprogram was contained. const DwarfCompileUnit *PrevCU; @@ -258,6 +233,7 @@ class DwarfDebug : public AsmPrinterHandler { MCSymbol *DwarfDebugLocSectionSym, *DwarfLineSectionSym, *DwarfAddrSectionSym; MCSymbol *FunctionBeginSym, *FunctionEndSym; MCSymbol *DwarfInfoDWOSectionSym, *DwarfAbbrevDWOSectionSym; + MCSymbol *DwarfTypesDWOSectionSym; MCSymbol *DwarfStrDWOSectionSym; MCSymbol *DwarfGnuPubNamesSectionSym, *DwarfGnuPubTypesSectionSym; @@ -322,6 +298,7 @@ class DwarfDebug : public AsmPrinterHandler { // True iff there are multiple CUs in this module. bool SingleCU; + bool IsDarwin; AddressPool AddrPool; @@ -334,8 +311,6 @@ class DwarfDebug : public AsmPrinterHandler { MCDwarfDwoLineTable *getDwoLineTable(const DwarfCompileUnit &); - void addScopeVariable(LexicalScope *LS, DbgVariable *Var); - const SmallVectorImpl<std::unique_ptr<DwarfUnit>> &getUnits() { return InfoHolder.getUnits(); } @@ -350,45 +325,8 @@ class DwarfDebug : public AsmPrinterHandler { void ensureAbstractVariableIsCreatedIfScoped(const 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); - - /// \brief A helper function to check whether the DIE for a given Scope is - /// going to be null. - bool isLexicalScopeDIENull(LexicalScope *Scope); - - /// \brief A helper function to construct a RangeSpanList for a given - /// lexical scope. - void addScopeRangeList(DwarfCompileUnit &TheCU, DIE &ScopeDIE, - const SmallVectorImpl<InsnRange> &Range); - - /// \brief Construct new DW_TAG_lexical_block for this scope and - /// attach DW_AT_low_pc/DW_AT_high_pc labels. - 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. - std::unique_ptr<DIE> constructInlinedScopeDIE(DwarfCompileUnit &TheCU, - LexicalScope *Scope); - - /// \brief Construct a DIE for this 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<std::unique_ptr<DIE>> &Children); + void constructAbstractSubprogramScopeDIE(LexicalScope *Scope); /// \brief Emit initial Dwarf sections with a label at the start of each one. void emitSectionLabels(); @@ -424,6 +362,10 @@ class DwarfDebug : public AsmPrinterHandler { /// the line matrix. void emitEndOfLineMatrix(unsigned SectionEnd); + /// \brief Emit a specified accelerator table. + void emitAccel(DwarfAccelTable &Accel, const MCSection *Section, + StringRef TableName, StringRef SymName); + /// \brief Emit visible names into a hashed accelerator table section. void emitAccelNames(); @@ -449,10 +391,9 @@ class DwarfDebug : public AsmPrinterHandler { /// index. void emitDebugPubTypes(bool GnuStyle = false); - void - emitDebugPubSection(bool GnuStyle, const MCSection *PSec, StringRef Name, - const StringMap<const DIE *> &(DwarfUnit::*Accessor)() - const); + void emitDebugPubSection( + bool GnuStyle, const MCSection *PSec, StringRef Name, + const StringMap<const DIE *> &(DwarfCompileUnit::*Accessor)() const); /// \brief Emit visible names into a debug str section. void emitDebugStr(); @@ -507,15 +448,8 @@ class DwarfDebug : public AsmPrinterHandler { DwarfCompileUnit &constructDwarfCompileUnit(DICompileUnit DIUnit); /// \brief Construct imported_module or imported_declaration DIE. - void constructImportedEntityDIE(DwarfCompileUnit &TheCU, const MDNode *N); - - /// \brief Construct import_module DIE. - void constructImportedEntityDIE(DwarfCompileUnit &TheCU, const MDNode *N, - DIE &Context); - - /// \brief Construct import_module DIE. - void constructImportedEntityDIE(DwarfCompileUnit &TheCU, - const DIImportedEntity &Module, DIE &Context); + void constructAndAddImportedEntityDIE(DwarfCompileUnit &TheCU, + const MDNode *N); /// \brief Register a source line with debug info. Returns the unique /// label that was emitted and which provides correspondence to the @@ -527,38 +461,29 @@ class DwarfDebug : public AsmPrinterHandler { /// ending of a scope. void identifyScopeMarkers(); - /// \brief If Var is an current function argument that add it in - /// CurrentFnArguments list. - bool addCurrentFnArgument(DbgVariable *Var, LexicalScope *Scope); - /// \brief Populate LexicalScope entries with variables' info. - void collectVariableInfo(SmallPtrSet<const MDNode *, 16> &ProcessedVars); + void collectVariableInfo(DwarfCompileUnit &TheCU, DISubprogram SP, + SmallPtrSetImpl<const MDNode *> &ProcessedVars); + + /// \brief Build the location list for all DBG_VALUEs in the + /// function that describe the same variable. + void buildLocationList(SmallVectorImpl<DebugLocEntry> &DebugLoc, + const DbgValueHistoryMap::InstrRanges &Ranges); /// \brief Collect variable information from the side table maintained /// by MMI. - void collectVariableInfoFromMMITable(SmallPtrSet<const MDNode *, 16> &P); + void collectVariableInfoFromMMITable(SmallPtrSetImpl<const MDNode *> &P); /// \brief Ensure that a label will be emitted before MI. void requestLabelBeforeInsn(const MachineInstr *MI) { LabelsBeforeInsn.insert(std::make_pair(MI, nullptr)); } - /// \brief Return Label preceding the instruction. - MCSymbol *getLabelBeforeInsn(const MachineInstr *MI); - /// \brief Ensure that a label will be emitted after MI. void requestLabelAfterInsn(const MachineInstr *MI) { LabelsAfterInsn.insert(std::make_pair(MI, nullptr)); } - /// \brief Return Label immediately following the instruction. - MCSymbol *getLabelAfterInsn(const MachineInstr *MI); - - void attachRangesOrLowHighPC(DwarfCompileUnit &Unit, DIE &D, - const SmallVectorImpl<InsnRange> &Ranges); - void attachLowHighPC(DwarfCompileUnit &Unit, DIE &D, MCSymbol *Begin, - MCSymbol *End); - public: //===--------------------------------------------------------------------===// // Main entry points. @@ -567,13 +492,6 @@ public: ~DwarfDebug() override; - void insertDIE(const MDNode *TypeMD, DIE *Die) { - MDTypeNodeToDieMap.insert(std::make_pair(TypeMD, Die)); - } - DIE *getDIE(const MDNode *TypeMD) { - return MDTypeNodeToDieMap.lookup(TypeMD); - } - /// \brief Emit all Dwarf sections that should come prior to the /// content. void beginModule(); @@ -626,11 +544,15 @@ public: /// Returns the section symbol for the .debug_loc section. MCSymbol *getDebugLocSym() const { return DwarfDebugLocSectionSym; } - /// Returns the previous section that was emitted into. - const MCSection *getPrevSection() const { return PrevSection; } + /// Returns the section symbol for the .debug_str section. + MCSymbol *getDebugStrSym() const { return DwarfStrSectionSym; } + + /// Returns the section symbol for the .debug_ranges section. + MCSymbol *getRangeSectionSym() const { return DwarfDebugRangeSectionSym; } /// Returns the previous CU that was being updated const DwarfCompileUnit *getPrevCU() const { return PrevCU; } + void setPrevCU(const DwarfCompileUnit *PrevCU) { this->PrevCU = PrevCU; } /// Returns the entries for the .debug_loc section. const SmallVectorImpl<DebugLocList> & @@ -641,6 +563,13 @@ public: /// \brief Emit an entry for the debug loc section. This can be used to /// handle an entry that's going to be emitted into the debug loc section. void emitDebugLocEntry(ByteStreamer &Streamer, const DebugLocEntry &Entry); + /// \brief emit a single value for the debug loc section. + void emitDebugLocValue(ByteStreamer &Streamer, + const DebugLocEntry::Value &Value); + /// Emits an optimal (=sorted) sequence of DW_OP_pieces. + void emitLocPieces(ByteStreamer &Streamer, + const DITypeIdentifierMap &Map, + ArrayRef<DebugLocEntry::Value> Values); /// Emit the location for a debug loc entry, including the size header. void emitDebugLocEntryLocation(const DebugLocEntry &Entry); @@ -674,6 +603,40 @@ public: void addAccelNamespace(StringRef Name, const DIE &Die); void addAccelType(StringRef Name, const DIE &Die, char Flags); + + const MachineFunction *getCurrentFunction() const { return CurFn; } + const MCSymbol *getFunctionBeginSym() const { return FunctionBeginSym; } + const MCSymbol *getFunctionEndSym() const { return FunctionEndSym; } + + iterator_range<ImportedEntityMap::const_iterator> + findImportedEntitiesForScope(const MDNode *Scope) const { + return make_range(std::equal_range( + ScopesWithImportedEntities.begin(), ScopesWithImportedEntities.end(), + std::pair<const MDNode *, const MDNode *>(Scope, nullptr), + less_first())); + } + + /// \brief A helper function to check whether the DIE for a given Scope is + /// going to be null. + bool isLexicalScopeDIENull(LexicalScope *Scope); + + /// \brief Return Label preceding the instruction. + MCSymbol *getLabelBeforeInsn(const MachineInstr *MI); + + /// \brief Return Label immediately following the instruction. + MCSymbol *getLabelAfterInsn(const MachineInstr *MI); + + // FIXME: Consider rolling ranges up into DwarfDebug since we use a single + // range_base anyway, so there's no need to keep them as separate per-CU range + // lists. (though one day we might end up with a range.dwo section, in which + // case it'd go to DwarfFile) + unsigned getNextRangeNumber() { return GlobalRangeCount++; } + + // FIXME: Sink these functions down into DwarfFile/Dwarf*Unit. + + SmallPtrSet<const MDNode *, 16> &getProcessedSPNodes() { + return ProcessedSPNodes; + } }; } // End of namespace llvm diff --git a/lib/CodeGen/AsmPrinter/DwarfException.h b/lib/CodeGen/AsmPrinter/DwarfException.h index 0440fce..e8867c0 100644 --- a/lib/CodeGen/AsmPrinter/DwarfException.h +++ b/lib/CodeGen/AsmPrinter/DwarfException.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CODEGEN_ASMPRINTER_DWARFEXCEPTION_H -#define LLVM_CODEGEN_ASMPRINTER_DWARFEXCEPTION_H +#ifndef LLVM_LIB_CODEGEN_ASMPRINTER_DWARFEXCEPTION_H +#define LLVM_LIB_CODEGEN_ASMPRINTER_DWARFEXCEPTION_H #include "EHStreamer.h" #include "llvm/CodeGen/AsmPrinter.h" @@ -81,39 +81,6 @@ public: /// endFunction - Gather and emit post-function exception information. void endFunction(const MachineFunction *) override; }; - -class Win64Exception : public EHStreamer { - /// shouldEmitPersonality - Per-function flag to indicate if personality - /// info should be emitted. - bool shouldEmitPersonality; - - /// shouldEmitLSDA - Per-function flag to indicate if the LSDA - /// should be emitted. - bool shouldEmitLSDA; - - /// shouldEmitMoves - Per-function flag to indicate if frame moves info - /// should be emitted. - bool shouldEmitMoves; - -public: - //===--------------------------------------------------------------------===// - // Main entry points. - // - Win64Exception(AsmPrinter *A); - virtual ~Win64Exception(); - - /// endModule - Emit all exception information that should come after the - /// content. - void endModule() override; - - /// beginFunction - Gather pre-function exception information. Assumes being - /// emitted immediately after the function entry point. - void beginFunction(const MachineFunction *MF) override; - - /// endFunction - Gather and emit post-function exception information. - void endFunction(const MachineFunction *) override; -}; - } // End of namespace llvm #endif diff --git a/lib/CodeGen/AsmPrinter/DwarfFile.cpp b/lib/CodeGen/AsmPrinter/DwarfFile.cpp index 737ee54..50180ea 100644 --- a/lib/CodeGen/AsmPrinter/DwarfFile.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfFile.cpp @@ -18,8 +18,9 @@ #include "llvm/Target/TargetLoweringObjectFile.h" namespace llvm { -DwarfFile::DwarfFile(AsmPrinter *AP, StringRef Pref, BumpPtrAllocator &DA) - : Asm(AP), StrPool(DA, *Asm, Pref) {} +DwarfFile::DwarfFile(AsmPrinter *AP, DwarfDebug &DD, StringRef Pref, + BumpPtrAllocator &DA) + : Asm(AP), DD(DD), StrPool(DA, *Asm, Pref) {} DwarfFile::~DwarfFile() {} @@ -48,25 +49,18 @@ void DwarfFile::addUnit(std::unique_ptr<DwarfUnit> 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) { +void DwarfFile::emitUnits(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()); + DD.emitDIE(Die); } } + // Compute the size and offset for each DIE. void DwarfFile::computeSizeAndOffsets() { // Offset from the first CU in the debug info section is 0 initially. @@ -149,8 +143,44 @@ void DwarfFile::emitAbbrevs(const MCSection *Section) { // Emit strings into a string section. void DwarfFile::emitStrings(const MCSection *StrSection, - const MCSection *OffsetSection, - const MCSymbol *StrSecSym) { - StrPool.emit(*Asm, StrSection, OffsetSection, StrSecSym); + const MCSection *OffsetSection) { + StrPool.emit(*Asm, StrSection, OffsetSection); +} + +void DwarfFile::addScopeVariable(LexicalScope *LS, DbgVariable *Var) { + SmallVectorImpl<DbgVariable *> &Vars = ScopeVariables[LS]; + DIVariable DV = Var->getVariable(); + // Variables with positive arg numbers are parameters. + if (unsigned ArgNum = DV.getArgNumber()) { + // Keep all parameters in order at the start of the variable list to ensure + // function types are correct (no out-of-order parameters) + // + // This could be improved by only doing it for optimized builds (unoptimized + // builds have the right order to begin with), searching from the back (this + // would catch the unoptimized case quickly), or doing a binary search + // rather than linear search. + auto I = Vars.begin(); + while (I != Vars.end()) { + unsigned CurNum = (*I)->getVariable().getArgNumber(); + // A local (non-parameter) variable has been found, insert immediately + // before it. + if (CurNum == 0) + break; + // A later indexed parameter has been found, insert immediately before it. + if (CurNum > ArgNum) + break; + // FIXME: There are still some cases where two inlined functions are + // conflated together (two calls to the same function at the same + // location (eg: via a macro, or without column info, etc)) and then + // their arguments are conflated as well. + assert((LS->getParent() || CurNum != ArgNum) && + "Duplicate argument for top level (non-inlined) function"); + ++I; + } + Vars.insert(I, Var); + return; + } + + Vars.push_back(Var); } } diff --git a/lib/CodeGen/AsmPrinter/DwarfFile.h b/lib/CodeGen/AsmPrinter/DwarfFile.h index 3985eb2..9d64bfc 100644 --- a/lib/CodeGen/AsmPrinter/DwarfFile.h +++ b/lib/CodeGen/AsmPrinter/DwarfFile.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef CODEGEN_ASMPRINTER_DWARFFILE_H__ -#define CODEGEN_ASMPRINTER_DWARFFILE_H__ +#ifndef LLVM_LIB_CODEGEN_ASMPRINTER_DWARFFILE_H +#define LLVM_LIB_CODEGEN_ASMPRINTER_DWARFFILE_H #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/FoldingSet.h" @@ -24,10 +24,13 @@ namespace llvm { class AsmPrinter; +class DbgVariable; class DwarfUnit; class DIEAbbrev; class MCSymbol; class DIE; +class DISubprogram; +class LexicalScope; class StringRef; class DwarfDebug; class MCSection; @@ -35,6 +38,8 @@ class DwarfFile { // Target of Dwarf emission, used for sizing of abbreviations. AsmPrinter *Asm; + DwarfDebug ⅅ + // Used to uniquely define abbreviations. FoldingSet<DIEAbbrev> AbbreviationsSet; @@ -46,8 +51,20 @@ class DwarfFile { DwarfStringPool StrPool; + // Collection of dbg variables of a scope. + DenseMap<LexicalScope *, SmallVector<DbgVariable *, 8>> ScopeVariables; + + // Collection of abstract subprogram DIEs. + DenseMap<const MDNode *, DIE *> AbstractSPDies; + + /// Maps MDNodes for type system with the corresponding DIEs. These DIEs can + /// be shared across CUs, that is why we keep the map here instead + /// of in DwarfCompileUnit. + DenseMap<const MDNode *, DIE *> MDTypeNodeToDieMap; + public: - DwarfFile(AsmPrinter *AP, StringRef Pref, BumpPtrAllocator &DA); + DwarfFile(AsmPrinter *AP, DwarfDebug &DD, StringRef Pref, + BumpPtrAllocator &DA); ~DwarfFile(); @@ -67,18 +84,34 @@ public: /// \brief Emit all of the units to the section listed with the given /// abbreviation section. - void emitUnits(DwarfDebug *DD, const MCSymbol *ASectionSym); + void emitUnits(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); + const MCSection *OffsetSection = nullptr); /// \brief Returns the string pool. DwarfStringPool &getStringPool() { return StrPool; } + + void addScopeVariable(LexicalScope *LS, DbgVariable *Var); + + DenseMap<LexicalScope *, SmallVector<DbgVariable *, 8>> &getScopeVariables() { + return ScopeVariables; + } + + DenseMap<const MDNode *, DIE *> &getAbstractSPDies() { + return AbstractSPDies; + } + + void insertDIE(const MDNode *TypeMD, DIE *Die) { + MDTypeNodeToDieMap.insert(std::make_pair(TypeMD, Die)); + } + DIE *getDIE(const MDNode *TypeMD) { + return MDTypeNodeToDieMap.lookup(TypeMD); + } }; } #endif diff --git a/lib/CodeGen/AsmPrinter/DwarfStringPool.cpp b/lib/CodeGen/AsmPrinter/DwarfStringPool.cpp index 72cab60..d76b66c 100644 --- a/lib/CodeGen/AsmPrinter/DwarfStringPool.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfStringPool.cpp @@ -12,14 +12,11 @@ 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(); + std::pair<MCSymbol *, unsigned> &Entry = Pool[Str]; if (!Entry.first) { Entry.second = Pool.size() - 1; Entry.first = Asm.GetTempSymbol(Prefix, Entry.second); @@ -36,8 +33,7 @@ unsigned DwarfStringPool::getIndex(AsmPrinter &Asm, StringRef Str) { } void DwarfStringPool::emit(AsmPrinter &Asm, const MCSection *StrSection, - const MCSection *OffsetSection, - const MCSymbol *StrSecSym) { + const MCSection *OffsetSection) { if (Pool.empty()) return; diff --git a/lib/CodeGen/AsmPrinter/DwarfStringPool.h b/lib/CodeGen/AsmPrinter/DwarfStringPool.h index c1615fb..ab32c1b 100644 --- a/lib/CodeGen/AsmPrinter/DwarfStringPool.h +++ b/lib/CodeGen/AsmPrinter/DwarfStringPool.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef CODEGEN_ASMPRINTER_STRINGPOOL_H__ -#define CODEGEN_ASMPRINTER_STRINGPOOL_H__ +#ifndef LLVM_LIB_CODEGEN_ASMPRINTER_DWARFSTRINGPOOL_H +#define LLVM_LIB_CODEGEN_ASMPRINTER_DWARFSTRINGPOOL_H #include "llvm/ADT/StringMap.h" #include "llvm/CodeGen/AsmPrinter.h" @@ -28,18 +28,13 @@ class StringRef; 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)) {} + : Pool(A), Prefix(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(); + const MCSection *OffsetSection = nullptr); /// \brief Returns an entry into the string pool with the given /// string text. diff --git a/lib/CodeGen/AsmPrinter/DwarfUnit.cpp b/lib/CodeGen/AsmPrinter/DwarfUnit.cpp index 9538bee..919d9d2 100644 --- a/lib/CodeGen/AsmPrinter/DwarfUnit.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfUnit.cpp @@ -12,7 +12,9 @@ //===----------------------------------------------------------------------===// #include "DwarfUnit.h" + #include "DwarfAccelTable.h" +#include "DwarfCompileUnit.h" #include "DwarfDebug.h" #include "llvm/ADT/APFloat.h" #include "llvm/IR/Constants.h" @@ -30,6 +32,7 @@ #include "llvm/Target/TargetLoweringObjectFile.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Target/TargetSubtargetInfo.h" using namespace llvm; @@ -44,20 +47,12 @@ GenerateDwarfTypeUnits("generate-type-units", cl::Hidden, 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) { + DD(DW), DU(DWU), IndexTyDie(nullptr), Section(nullptr) { assert(UnitTag == dwarf::DW_TAG_compile_unit || UnitTag == dwarf::DW_TAG_type_unit); DIEIntegerOne = new (DIEValueAllocator) DIEInteger(1); } -DwarfCompileUnit::DwarfCompileUnit(unsigned UID, DICompileUnit Node, - AsmPrinter *A, DwarfDebug *DW, - DwarfFile *DWU) - : DwarfUnit(UID, dwarf::DW_TAG_compile_unit, Node, A, DW, DWU) { - insertDIE(Node, &getUnitDie()); -} - DwarfTypeUnit::DwarfTypeUnit(unsigned UID, DwarfCompileUnit &CU, AsmPrinter *A, DwarfDebug *DW, DwarfFile *DWU, MCDwarfDwoLineTable *SplitLineTable) @@ -146,7 +141,7 @@ static bool isShareableAcrossCUs(DIDescriptor D) { /// will be kept in DwarfDebug for shareable DIEs. DIE *DwarfUnit::getDIE(DIDescriptor D) const { if (isShareableAcrossCUs(D)) - return DD->getDIE(D); + return DU->getDIE(D); return MDNodeToDieMap.lookup(D); } @@ -155,7 +150,7 @@ DIE *DwarfUnit::getDIE(DIDescriptor D) const { /// will be kept in DwarfDebug for shareable DIEs. void DwarfUnit::insertDIE(DIDescriptor Desc, DIE *D) { if (isShareableAcrossCUs(Desc)) { - DD->insertDIE(Desc, D); + DU->insertDIE(Desc, D); return; } MDNodeToDieMap.insert(std::make_pair(Desc, D)); @@ -206,10 +201,14 @@ void DwarfUnit::addSInt(DIELoc &Die, Optional<dwarf::Form> Form, /// table. void DwarfUnit::addString(DIE &Die, dwarf::Attribute Attribute, StringRef String) { - - if (!DD->useSplitDwarf()) + if (!isDwoUnit()) return addLocalString(Die, Attribute, String); + addIndexedString(Die, Attribute, String); +} + +void DwarfUnit::addIndexedString(DIE &Die, dwarf::Attribute Attribute, + StringRef String) { unsigned idx = DU->getStringPool().getIndex(*Asm, String); DIEValue *Value = new (DIEValueAllocator) DIEInteger(idx); DIEValue *Str = new (DIEValueAllocator) DIEString(Value, String); @@ -224,31 +223,12 @@ void DwarfUnit::addLocalString(DIE &Die, dwarf::Attribute Attribute, DIEValue *Value; if (Asm->MAI->doesDwarfUseRelocationsAcrossSections()) Value = new (DIEValueAllocator) DIELabel(Symb); - else { - MCSymbol *StringPool = DU->getStringPool().getSectionSymbol(); - Value = new (DIEValueAllocator) DIEDelta(Symb, StringPool); - } + else + Value = new (DIEValueAllocator) DIEDelta(Symb, DD->getDebugStrSym()); DIEValue *Str = new (DIEValueAllocator) DIEString(Value, String); Die.addValue(Attribute, dwarf::DW_FORM_strp, Str); } -/// addExpr - Add a Dwarf expression attribute data and value. -/// -void DwarfUnit::addExpr(DIELoc &Die, dwarf::Form Form, const MCExpr *Expr) { - DIEValue *Value = new (DIEValueAllocator) DIEExpr(Expr); - Die.addValue((dwarf::Attribute)0, Form, Value); -} - -/// addLocationList - Add a Dwarf loclistptr attribute data and value. -/// -void DwarfUnit::addLocationList(DIE &Die, dwarf::Attribute Attribute, - unsigned Index) { - DIEValue *Value = new (DIEValueAllocator) DIELocList(Index); - dwarf::Form Form = DD->getDwarfVersion() >= 4 ? dwarf::DW_FORM_sec_offset - : dwarf::DW_FORM_data4; - Die.addValue(Attribute, Form, Value); -} - /// addLabel - Add a Dwarf label attribute data and value. /// void DwarfUnit::addLabel(DIE &Die, dwarf::Attribute Attribute, dwarf::Form Form, @@ -261,16 +241,6 @@ void DwarfUnit::addLabel(DIELoc &Die, dwarf::Form Form, const MCSymbol *Label) { addLabel(Die, (dwarf::Attribute)0, Form, Label); } -/// addSectionLabel - Add a Dwarf section label attribute data and value. -/// -void DwarfUnit::addSectionLabel(DIE &Die, dwarf::Attribute Attribute, - const MCSymbol *Label) { - if (DD->getDwarfVersion() >= 4) - addLabel(Die, Attribute, dwarf::DW_FORM_sec_offset, Label); - else - addLabel(Die, Attribute, dwarf::DW_FORM_data4, Label); -} - /// addSectionOffset - Add an offset into a section attribute data and value. /// void DwarfUnit::addSectionOffset(DIE &Die, dwarf::Attribute Attribute, @@ -281,45 +251,6 @@ void DwarfUnit::addSectionOffset(DIE &Die, dwarf::Attribute Attribute, addUInt(Die, Attribute, dwarf::DW_FORM_data4, Integer); } -/// addLabelAddress - Add a dwarf label attribute data and value using -/// DW_FORM_addr or DW_FORM_GNU_addr_index. -/// -void DwarfCompileUnit::addLabelAddress(DIE &Die, dwarf::Attribute Attribute, - const MCSymbol *Label) { - - if (!DD->useSplitDwarf()) - return addLocalLabelAddress(Die, Attribute, Label); - - if (Label) - DD->addArangeLabel(SymbolCU(this, Label)); - - unsigned idx = DD->getAddressPool().getIndex(Label); - DIEValue *Value = new (DIEValueAllocator) DIEInteger(idx); - Die.addValue(Attribute, dwarf::DW_FORM_GNU_addr_index, Value); -} - -void DwarfCompileUnit::addLocalLabelAddress(DIE &Die, - dwarf::Attribute Attribute, - const MCSymbol *Label) { - if (Label) - DD->addArangeLabel(SymbolCU(this, Label)); - - Die.addValue(Attribute, dwarf::DW_FORM_addr, - Label ? (DIEValue *)new (DIEValueAllocator) DIELabel(Label) - : new (DIEValueAllocator) DIEInteger(0)); -} - -unsigned DwarfCompileUnit::getOrCreateSourceID(StringRef FileName, StringRef DirName) { - // If we print assembly, we can't separate .file entries according to - // compile units. Thus all files will belong to the default compile unit. - - // FIXME: add a better feature test than hasRawTextSupport. Even better, - // extend .file to support this. - return Asm->OutStreamer.EmitDwarfFileDirective( - 0, DirName, FileName, - Asm->OutStreamer.hasRawTextSupport() ? 0 : getUniqueID()); -} - unsigned DwarfTypeUnit::getOrCreateSourceID(StringRef FileName, StringRef DirName) { return SplitLineTable ? SplitLineTable->getFile(DirName, FileName) : getCU().getOrCreateSourceID(FileName, DirName); @@ -339,16 +270,6 @@ void DwarfUnit::addOpAddress(DIELoc &Die, const MCSymbol *Sym) { } } -/// addSectionDelta - Add a section label delta attribute data and value. -/// -void DwarfUnit::addSectionDelta(DIE &Die, dwarf::Attribute Attribute, - const MCSymbol *Hi, const MCSymbol *Lo) { - DIEValue *Value = new (DIEValueAllocator) DIEDelta(Hi, Lo); - Die.addValue(Attribute, DD->getDwarfVersion() >= 4 ? dwarf::DW_FORM_sec_offset - : dwarf::DW_FORM_data4, - Value); -} - void DwarfUnit::addLabelDelta(DIE &Die, dwarf::Attribute Attribute, const MCSymbol *Hi, const MCSymbol *Lo) { DIEValue *Value = new (DIEValueAllocator) DIEDelta(Hi, Lo); @@ -477,22 +398,12 @@ void DwarfUnit::addSourceLine(DIE &Die, DINameSpace NS) { addSourceLine(Die, NS.getLineNumber(), NS.getFilename(), NS.getDirectory()); } -/// addVariableAddress - Add DW_AT_location attribute for a -/// DbgVariable based on provided MachineLocation. -void DwarfUnit::addVariableAddress(const DbgVariable &DV, DIE &Die, - MachineLocation Location) { - if (DV.variableHasComplexAddress()) - addComplexAddress(DV, Die, dwarf::DW_AT_location, Location); - else if (DV.isBlockByrefVariable()) - addBlockByrefAddress(DV, Die, dwarf::DW_AT_location, Location); - else - addAddress(Die, dwarf::DW_AT_location, Location, - DV.getVariable().isIndirect()); -} - /// addRegisterOp - Add register operand. -void DwarfUnit::addRegisterOp(DIELoc &TheDie, unsigned Reg) { - const TargetRegisterInfo *RI = Asm->TM.getRegisterInfo(); +// FIXME: Ideally, this would share the implementation with +// AsmPrinter::EmitDwarfRegOpPiece. +void DwarfUnit::addRegisterOpPiece(DIELoc &TheDie, unsigned Reg, + unsigned SizeInBits, unsigned OffsetInBits) { + const TargetRegisterInfo *RI = Asm->TM.getSubtargetImpl()->getRegisterInfo(); int DWReg = RI->getDwarfRegNum(Reg, false); bool isSubRegister = DWReg < 0; @@ -511,7 +422,7 @@ void DwarfUnit::addRegisterOp(DIELoc &TheDie, unsigned Reg) { return; } - // Emit register + // Emit register. if (DWReg < 32) addUInt(TheDie, dwarf::DW_FORM_data1, dwarf::DW_OP_reg0 + DWReg); else { @@ -519,18 +430,34 @@ void DwarfUnit::addRegisterOp(DIELoc &TheDie, unsigned Reg) { addUInt(TheDie, dwarf::DW_FORM_udata, DWReg); } - // Emit Mask - if (isSubRegister) { - unsigned Size = RI->getSubRegIdxSize(Idx); - unsigned Offset = RI->getSubRegIdxOffset(Idx); - if (Offset > 0) { + // Emit mask. + bool isPiece = SizeInBits > 0; + if (isSubRegister || isPiece) { + const unsigned SizeOfByte = 8; + unsigned RegSizeInBits = RI->getSubRegIdxSize(Idx); + unsigned RegOffsetInBits = RI->getSubRegIdxOffset(Idx); + unsigned PieceSizeInBits = std::max(SizeInBits, RegSizeInBits); + unsigned PieceOffsetInBits = OffsetInBits ? OffsetInBits : RegOffsetInBits; + assert(RegSizeInBits >= SizeInBits && "register smaller than value"); + + if (RegOffsetInBits != PieceOffsetInBits) { + // Manually shift the value into place, since the DW_OP_piece + // describes the part of the variable, not the position of the + // subregister. + addUInt(TheDie, dwarf::DW_FORM_data1, dwarf::DW_OP_constu); + addUInt(TheDie, dwarf::DW_FORM_data1, RegOffsetInBits); + addUInt(TheDie, dwarf::DW_FORM_data1, dwarf::DW_OP_shr); + } + + if (PieceOffsetInBits > 0 || PieceSizeInBits % SizeOfByte) { + assert(PieceSizeInBits > 0 && "piece has zero size"); addUInt(TheDie, dwarf::DW_FORM_data1, dwarf::DW_OP_bit_piece); - addUInt(TheDie, dwarf::DW_FORM_data1, Size); - addUInt(TheDie, dwarf::DW_FORM_data1, Offset); - } else { - unsigned ByteSize = Size / 8; // Assuming 8 bits per byte. + addUInt(TheDie, dwarf::DW_FORM_data1, PieceSizeInBits); + addUInt(TheDie, dwarf::DW_FORM_data1, PieceOffsetInBits); + } else { + assert(PieceSizeInBits > 0 && "piece has zero size"); addUInt(TheDie, dwarf::DW_FORM_data1, dwarf::DW_OP_piece); - addUInt(TheDie, dwarf::DW_FORM_data1, ByteSize); + addUInt(TheDie, dwarf::DW_FORM_data1, PieceSizeInBits/SizeOfByte); } } } @@ -538,9 +465,9 @@ void DwarfUnit::addRegisterOp(DIELoc &TheDie, unsigned Reg) { /// addRegisterOffset - Add register offset. void DwarfUnit::addRegisterOffset(DIELoc &TheDie, unsigned Reg, int64_t Offset) { - const TargetRegisterInfo *RI = Asm->TM.getRegisterInfo(); + const TargetRegisterInfo *RI = Asm->TM.getSubtargetImpl()->getRegisterInfo(); unsigned DWReg = RI->getDwarfRegNum(Reg, false); - const TargetRegisterInfo *TRI = Asm->TM.getRegisterInfo(); + const TargetRegisterInfo *TRI = Asm->TM.getSubtargetImpl()->getRegisterInfo(); if (Reg == TRI->getFrameRegister(*Asm->MF)) // If variable offset is based in frame register then use fbreg. addUInt(TheDie, dwarf::DW_FORM_data1, dwarf::DW_OP_fbreg); @@ -553,63 +480,6 @@ void DwarfUnit::addRegisterOffset(DIELoc &TheDie, unsigned Reg, addSInt(TheDie, dwarf::DW_FORM_sdata, Offset); } -/// addAddress - Add an address attribute to a die based on the location -/// provided. -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()); - else { - addRegisterOffset(*Loc, Location.getReg(), Location.getOffset()); - if (Indirect && !Location.isReg()) { - addUInt(*Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_deref); - } - } - - // Now attach the location information to the DIE. - addBlock(Die, Attribute, Loc); -} - -/// addComplexAddress - Start with the address based on the location provided, -/// and generate the DWARF information necessary to find the actual variable -/// given the extra address information encoded in the DbgVariable, starting -/// from the starting location. Add the DWARF information to the die. -/// -void DwarfUnit::addComplexAddress(const DbgVariable &DV, DIE &Die, - dwarf::Attribute Attribute, - const MachineLocation &Location) { - DIELoc *Loc = new (DIEValueAllocator) DIELoc(); - unsigned N = DV.getNumAddrElements(); - unsigned i = 0; - if (Location.isReg()) { - if (N >= 2 && DV.getAddrElement(0) == DIBuilder::OpPlus) { - // If first address element is OpPlus then emit - // DW_OP_breg + Offset instead of DW_OP_reg + Offset. - addRegisterOffset(*Loc, Location.getReg(), DV.getAddrElement(1)); - i = 2; - } else - addRegisterOp(*Loc, Location.getReg()); - } else - 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)); - } else if (Element == DIBuilder::OpDeref) { - if (!Location.isReg()) - addUInt(*Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_deref); - } else - llvm_unreachable("unknown DIBuilder Opcode"); - } - - // Now attach the location information to the DIE. - addBlock(Die, Attribute, Loc); -} - /* Byref variables, in Blocks, are declared by the programmer as "SomeType VarName;", but the compiler creates a __Block_byref_x_VarName struct, and gives the variable VarName either the struct, or a pointer to the struct, as @@ -690,7 +560,7 @@ void DwarfUnit::addBlockByrefAddress(const DbgVariable &DV, DIE &Die, // Find the __forwarding field and the variable field in the __Block_byref // struct. - DIArray Fields = blockStruct.getTypeArray(); + DIArray Fields = blockStruct.getElements(); DIDerivedType varField; DIDerivedType forwardingField; @@ -712,7 +582,7 @@ void DwarfUnit::addBlockByrefAddress(const DbgVariable &DV, DIE &Die, DIELoc *Loc = new (DIEValueAllocator) DIELoc(); if (Location.isReg()) - addRegisterOp(*Loc, Location.getReg()); + addRegisterOpPiece(*Loc, Location.getReg()); else addRegisterOffset(*Loc, Location.getReg(), Location.getOffset()); @@ -1002,11 +872,9 @@ void DwarfUnit::updateAcceleratorTables(DIScope Context, DIType Ty, unsigned Flags = IsImplementation ? dwarf::DW_FLAG_type_implementation : 0; 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; + if (!Context || Context.isCompileUnit() || Context.isFile() || + Context.isNameSpace()) + addGlobalType(Ty, TyDIE, Context); } } @@ -1031,14 +899,6 @@ void DwarfUnit::addType(DIE &Entity, DIType Ty, dwarf::Attribute Attribute) { addDIEEntry(Entity, Attribute, Entry); } -/// addGlobalName - Add a new global name to the compile unit. -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; -} - /// getParentContextString - Walks the metadata parent chain in a language /// specific manner (using the compile unit language) and returns /// it as a string. This is done at the metadata level because DIEs may @@ -1129,16 +989,16 @@ void DwarfUnit::constructTypeDIE(DIE &Buffer, DIDerivedType DTy) { } /// constructSubprogramArguments - Construct function argument DIEs. -void DwarfUnit::constructSubprogramArguments(DIE &Buffer, DIArray Args) { +void DwarfUnit::constructSubprogramArguments(DIE &Buffer, DITypeArray Args) { for (unsigned i = 1, N = Args.getNumElements(); i < N; ++i) { - DIDescriptor Ty = Args.getElement(i); - if (Ty.isUnspecifiedParameter()) { + DIType Ty = resolve(Args.getElement(i)); + if (!Ty) { assert(i == N-1 && "Unspecified parameter must be the last argument"); createAndAddDIE(dwarf::DW_TAG_unspecified_parameters, Buffer); } else { DIE &Arg = createAndAddDIE(dwarf::DW_TAG_formal_parameter, Buffer); - addType(Arg, DIType(Ty)); - if (DIType(Ty).isArtificial()) + addType(Arg, Ty); + if (Ty.isArtificial()) addFlag(Arg, dwarf::DW_AT_artificial); } } @@ -1161,14 +1021,14 @@ void DwarfUnit::constructTypeDIE(DIE &Buffer, DICompositeType CTy) { break; case dwarf::DW_TAG_subroutine_type: { // Add return type. A void return won't have a type. - DIArray Elements = CTy.getTypeArray(); - DIType RTy(Elements.getElement(0)); + DITypeArray Elements = DISubroutineType(CTy).getTypeArray(); + DIType RTy(resolve(Elements.getElement(0))); if (RTy) addType(Buffer, RTy); bool isPrototyped = true; if (Elements.getNumElements() == 2 && - Elements.getElement(1).isUnspecifiedParameter()) + !Elements.getElement(1)) isPrototyped = false; constructSubprogramArguments(Buffer, Elements); @@ -1191,7 +1051,7 @@ void DwarfUnit::constructTypeDIE(DIE &Buffer, DICompositeType CTy) { case dwarf::DW_TAG_union_type: case dwarf::DW_TAG_class_type: { // Add elements to structure type. - DIArray Elements = CTy.getTypeArray(); + DIArray Elements = CTy.getElements(); for (unsigned i = 0, N = Elements.getNumElements(); i < N; ++i) { DIDescriptor Element = Elements.getElement(i); if (Element.isSubprogram()) @@ -1373,20 +1233,23 @@ DIE *DwarfUnit::getOrCreateNameSpace(DINameSpace NS) { } /// getOrCreateSubprogramDIE - Create new DIE using SP. -DIE *DwarfUnit::getOrCreateSubprogramDIE(DISubprogram SP) { +DIE *DwarfUnit::getOrCreateSubprogramDIE(DISubprogram SP, bool Minimal) { // Construct the context before querying for the existence of the DIE in case // such construction creates the DIE (as is the case for member function // declarations). - DIE *ContextDIE = getOrCreateContextDIE(resolve(SP.getContext())); + DIE *ContextDIE = + Minimal ? &getUnitDie() : getOrCreateContextDIE(resolve(SP.getContext())); if (DIE *SPDie = getDIE(SP)) return SPDie; if (DISubprogram SPDecl = SP.getFunctionDeclaration()) { - // Add subprogram definitions to the CU die directly. - ContextDIE = &getUnitDie(); - // Build the decl now to ensure it precedes the definition. - getOrCreateSubprogramDIE(SPDecl); + if (!Minimal) { + // Add subprogram definitions to the CU die directly. + ContextDIE = &getUnitDie(); + // Build the decl now to ensure it precedes the definition. + getOrCreateSubprogramDIE(SPDecl); + } } // DW_TAG_inlined_subroutine may refer to this DIE. @@ -1401,14 +1264,8 @@ DIE *DwarfUnit::getOrCreateSubprogramDIE(DISubprogram SP) { return &SPDie; } -void DwarfUnit::applySubprogramAttributesToDefinition(DISubprogram SP, DIE &SPDie) { - DISubprogram SPDecl = SP.getFunctionDeclaration(); - DIScope Context = resolve(SPDecl ? SPDecl.getContext() : SP.getContext()); - applySubprogramAttributes(SP, SPDie); - addGlobalName(SP.getName(), SPDie, Context); -} - -void DwarfUnit::applySubprogramAttributes(DISubprogram SP, DIE &SPDie) { +bool DwarfUnit::applySubprogramDefinitionAttributes(DISubprogram SP, + DIE &SPDie) { DIE *DeclDie = nullptr; StringRef DeclLinkageName; if (DISubprogram SPDecl = SP.getFunctionDeclaration()) { @@ -1431,17 +1288,29 @@ void DwarfUnit::applySubprogramAttributes(DISubprogram SP, DIE &SPDie) { 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; - } + if (!DeclDie) + return false; + + // Refer to the function declaration where all the other attributes will be + // found. + addDIEEntry(SPDie, dwarf::DW_AT_specification, *DeclDie); + return true; +} + +void DwarfUnit::applySubprogramAttributes(DISubprogram SP, DIE &SPDie, + bool Minimal) { + if (!Minimal) + if (applySubprogramDefinitionAttributes(SP, SPDie)) + return; // Constructors and operators for anonymous aggregates do not have names. if (!SP.getName().empty()) addString(SPDie, dwarf::DW_AT_name, SP.getName()); + // Skip the rest of the attributes under -gmlt to save space. + if (Minimal) + return; + addSourceLine(SPDie, SP); // Add the prototype if we have a prototype and we have a C like @@ -1452,15 +1321,15 @@ void DwarfUnit::applySubprogramAttributes(DISubprogram SP, DIE &SPDie) { Language == dwarf::DW_LANG_ObjC)) addFlag(SPDie, dwarf::DW_AT_prototyped); - DICompositeType SPTy = SP.getType(); + DISubroutineType SPTy = SP.getType(); assert(SPTy.getTag() == dwarf::DW_TAG_subroutine_type && "the type of a subprogram should be a subroutine"); - DIArray Args = SPTy.getTypeArray(); + DITypeArray Args = SPTy.getTypeArray(); // Add a return type. If this is a type like a C/C++ void type we don't add a // return type. - if (Args.getElement(0)) - addType(SPDie, DIType(Args.getElement(0))); + if (resolve(Args.getElement(0))) + addType(SPDie, DIType(resolve(Args.getElement(0)))); unsigned VK = SP.getVirtuality(); if (VK) { @@ -1506,7 +1375,7 @@ void DwarfUnit::applySubprogramAttributes(DISubprogram SP, DIE &SPDie) { else if (SP.isPrivate()) addUInt(SPDie, dwarf::DW_AT_accessibility, dwarf::DW_FORM_data1, dwarf::DW_ACCESS_private); - else + else if (SP.isPublic()) addUInt(SPDie, dwarf::DW_AT_accessibility, dwarf::DW_FORM_data1, dwarf::DW_ACCESS_public); @@ -1514,184 +1383,6 @@ void DwarfUnit::applySubprogramAttributes(DISubprogram SP, DIE &SPDie) { addFlag(SPDie, dwarf::DW_AT_explicit); } -void DwarfUnit::applyVariableAttributes(const DbgVariable &Var, - DIE &VariableDie) { - StringRef Name = Var.getName(); - if (!Name.empty()) - addString(VariableDie, dwarf::DW_AT_name, Name); - addSourceLine(VariableDie, Var.getVariable()); - addType(VariableDie, Var.getType()); - if (Var.isArtificial()) - addFlag(VariableDie, dwarf::DW_AT_artificial); -} - -// Return const expression if value is a GEP to access merged global -// constant. e.g. -// i8* getelementptr ({ i8, i8, i8, i8 }* @_MergedGlobals, i32 0, i32 0) -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 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 nullptr; - - // Second operand is zero. - const ConstantInt *CI = dyn_cast_or_null<ConstantInt>(CE->getOperand(1)); - if (!CI || !CI->isZero()) - return nullptr; - - // Third operand is offset. - if (!isa<ConstantInt>(CE->getOperand(2))) - return nullptr; - - return CE; -} - -/// createGlobalVariableDIE - create global variable DIE. -void DwarfCompileUnit::createGlobalVariableDIE(DIGlobalVariable GV) { - // Check for pre-existence. - if (getDIE(GV)) - return; - - assert(GV.isGlobalVariable()); - - DIScope GVContext = GV.getContext(); - DIType GTy = DD->resolve(GV.getType()); - - // If this is a static data member definition, some attributes belong - // to the declaration DIE. - DIE *VariableDIE = nullptr; - bool IsStaticMember = false; - DIDerivedType SDMDecl = GV.getStaticDataMemberDeclaration(); - if (SDMDecl.Verify()) { - assert(SDMDecl.isStaticMember() && "Expected static member decl"); - // We need the declaration DIE that is in the static member's class. - VariableDIE = getOrCreateStaticMemberDIE(SDMDecl); - IsStaticMember = true; - } - - // If this is not a static data member definition, create the variable - // DIE and add the initial set of attributes to it. - if (!VariableDIE) { - // Construct the context before querying for the existence of the DIE in - // case such construction creates the DIE. - DIE *ContextDIE = getOrCreateContextDIE(GVContext); - - // Add to map. - VariableDIE = &createAndAddDIE(GV.getTag(), *ContextDIE, GV); - - // Add name and type. - addString(*VariableDIE, dwarf::DW_AT_name, GV.getDisplayName()); - addType(*VariableDIE, GTy); - - // Add scoping info. - if (!GV.isLocalToUnit()) - addFlag(*VariableDIE, dwarf::DW_AT_external); - - // Add line number info. - addSourceLine(*VariableDIE, GV); - } - - // Add location. - bool addToAccelTable = false; - DIE *VariableSpecDIE = nullptr; - bool isGlobalVariable = GV.getGlobal() != nullptr; - if (isGlobalVariable) { - addToAccelTable = true; - DIELoc *Loc = new (DIEValueAllocator) DIELoc(); - const MCSymbol *Sym = Asm->getSymbol(GV.getGlobal()); - if (GV.getGlobal()->isThreadLocal()) { - // FIXME: Make this work with -gsplit-dwarf. - unsigned PointerSize = Asm->getDataLayout().getPointerSize(); - assert((PointerSize == 4 || PointerSize == 8) && - "Add support for other sizes if necessary"); - // 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, - 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, - Asm->getObjFileLowering().getDebugThreadLocalSymbol(Sym)); - } else { - 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); - } else { - DD->addArangeLabel(SymbolCU(this, Sym)); - addOpAddress(*Loc, Sym); - } - // Do not create specification DIE if context is either compile unit - // or a subprogram. - if (GVContext && GV.isDefinition() && !GVContext.isCompileUnit() && - !GVContext.isFile() && !DD->isSubprogramContext(GVContext)) { - // Create specification DIE. - VariableSpecDIE = &createAndAddDIE(dwarf::DW_TAG_variable, 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); - } else { - addBlock(*VariableDIE, dwarf::DW_AT_location, Loc); - } - // Add the linkage name. - StringRef LinkageName = GV.getLinkageName(); - if (!LinkageName.empty()) - // 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, - DD->getDwarfVersion() >= 4 ? dwarf::DW_AT_linkage_name - : dwarf::DW_AT_MIPS_linkage_name, - GlobalValue::getRealLinkageName(LinkageName)); - } else if (const ConstantInt *CI = - dyn_cast_or_null<ConstantInt>(GV.getConstant())) { - // AT_const_value was added when the static member was created. To avoid - // emitting AT_const_value multiple times, we only add AT_const_value when - // it is not a static member. - if (!IsStaticMember) - addConstantValue(*VariableDIE, CI, GTy); - } else if (const ConstantExpr *CE = getMergedGlobalExpr(GV->getOperand(11))) { - addToAccelTable = true; - // GV is a merged global. - DIELoc *Loc = new (DIEValueAllocator) DIELoc(); - 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); - SmallVector<Value *, 3> Idx(CE->op_begin() + 1, CE->op_end()); - 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); - } - - if (addToAccelTable) { - 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()) - DD->addAccelName(GV.getLinkageName(), AddrDIE); - } - - 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); @@ -1700,9 +1391,7 @@ void DwarfUnit::constructSubrangeDIE(DIE &Buffer, DISubrange SR, DIE *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 // Count == -1 then the array is unbounded and we do not emit - // DW_AT_lower_bound and DW_AT_upper_bound attributes. If LowerBound == 0 and - // Count == 0, then the array has zero elements in which case we do not emit - // an upper bound. + // DW_AT_lower_bound and DW_AT_count attributes. int64_t LowerBound = SR.getLo(); int64_t DefaultLowerBound = getDefaultLowerBound(); int64_t Count = SR.getCount(); @@ -1710,11 +1399,22 @@ void DwarfUnit::constructSubrangeDIE(DIE &Buffer, DISubrange SR, DIE *IndexTy) { if (DefaultLowerBound == -1 || LowerBound != DefaultLowerBound) addUInt(DW_Subrange, dwarf::DW_AT_lower_bound, None, LowerBound); - if (Count != -1 && Count != 0) + if (Count != -1) // FIXME: An unbounded array should reference the expression that defines // the array. - addUInt(DW_Subrange, dwarf::DW_AT_upper_bound, None, - LowerBound + Count - 1); + addUInt(DW_Subrange, dwarf::DW_AT_count, None, Count); +} + +DIE *DwarfUnit::getIndexTyDie() { + if (IndexTyDie) + return IndexTyDie; + // Construct an integer type to use for indexes. + IndexTyDie = &createAndAddDIE(dwarf::DW_TAG_base_type, UnitDie); + addString(*IndexTyDie, dwarf::DW_AT_name, "sizetype"); + addUInt(*IndexTyDie, dwarf::DW_AT_byte_size, None, sizeof(int64_t)); + addUInt(*IndexTyDie, dwarf::DW_AT_encoding, dwarf::DW_FORM_data1, + dwarf::DW_ATE_unsigned); + return IndexTyDie; } /// constructArrayTypeDIE - Construct array type DIE from DICompositeType. @@ -1729,18 +1429,9 @@ void DwarfUnit::constructArrayTypeDIE(DIE &Buffer, DICompositeType CTy) { // FIXME: This type should be passed down from the front end // as different languages may have different sizes for indexes. 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, - dwarf::DW_ATE_unsigned); - setIndexTyDie(IdxTy); - } // Add subranges to array type. - DIArray Elements = CTy.getTypeArray(); + DIArray Elements = CTy.getElements(); for (unsigned i = 0, N = Elements.getNumElements(); i < N; ++i) { DIDescriptor Element = Elements.getElement(i); if (Element.getTag() == dwarf::DW_TAG_subrange_type) @@ -1750,7 +1441,7 @@ void DwarfUnit::constructArrayTypeDIE(DIE &Buffer, DICompositeType CTy) { /// constructEnumTypeDIE - Construct an enum type DIE from DICompositeType. void DwarfUnit::constructEnumTypeDIE(DIE &Buffer, DICompositeType CTy) { - DIArray Elements = CTy.getTypeArray(); + DIArray Elements = CTy.getElements(); // Add enumerators to enumeration type. for (unsigned i = 0, N = Elements.getNumElements(); i < N; ++i) { @@ -1788,68 +1479,6 @@ void DwarfUnit::constructContainingTypeDIEs() { } } -/// constructVariableDIE - Construct a DIE for the given DbgVariable. -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) { - // Define variable debug information entry. - auto VariableDie = make_unique<DIE>(DV.getTag()); - - if (Abstract) { - applyVariableAttributes(DV, *VariableDie); - return VariableDie; - } - - // Add variable address. - - unsigned Offset = DV.getDotDebugLocOffset(); - if (Offset != ~0U) { - addLocationList(*VariableDie, dwarf::DW_AT_location, Offset); - return VariableDie; - } - - // Check if variable is described by a DBG_VALUE instruction. - if (const MachineInstr *DVInsn = DV.getMInsn()) { - assert(DVInsn->getNumOperands() == 3); - if (DVInsn->getOperand(0).isReg()) { - const MachineOperand RegOp = DVInsn->getOperand(0); - // If the second operand is an immediate, this is an indirect value. - if (DVInsn->getOperand(1).isImm()) { - MachineLocation Location(RegOp.getReg(), - DVInsn->getOperand(1).getImm()); - addVariableAddress(DV, *VariableDie, Location); - } else if (RegOp.getReg()) - addVariableAddress(DV, *VariableDie, MachineLocation(RegOp.getReg())); - } else if (DVInsn->getOperand(0).isImm()) - addConstantValue(*VariableDie, DVInsn->getOperand(0), DV.getType()); - else if (DVInsn->getOperand(0).isFPImm()) - addConstantFPValue(*VariableDie, DVInsn->getOperand(0)); - else if (DVInsn->getOperand(0).isCImm()) - addConstantValue(*VariableDie, DVInsn->getOperand(0).getCImm(), - DV.getType()); - - return 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); @@ -1922,7 +1551,7 @@ void DwarfUnit::constructMemberDIE(DIE &Buffer, DIDerivedType DT) { addUInt(MemberDie, dwarf::DW_AT_accessibility, dwarf::DW_FORM_data1, dwarf::DW_ACCESS_private); // Otherwise C++ member and base classes are considered public. - else + else if (DT.isPublic()) addUInt(MemberDie, dwarf::DW_AT_accessibility, dwarf::DW_FORM_data1, dwarf::DW_ACCESS_public); if (DT.isVirtual()) @@ -1971,7 +1600,7 @@ DIE *DwarfUnit::getOrCreateStaticMemberDIE(DIDerivedType DT) { else if (DT.isPrivate()) addUInt(StaticMemberDIE, dwarf::DW_AT_accessibility, dwarf::DW_FORM_data1, dwarf::DW_ACCESS_private); - else + else if (DT.isPublic()) addUInt(StaticMemberDIE, dwarf::DW_AT_accessibility, dwarf::DW_FORM_data1, dwarf::DW_ACCESS_public); @@ -1984,6 +1613,10 @@ DIE *DwarfUnit::getOrCreateStaticMemberDIE(DIDerivedType DT) { } void DwarfUnit::emitHeader(const MCSymbol *ASectionSym) const { + // Emit size of content not including length itself + Asm->OutStreamer.AddComment("Length of Unit"); + Asm->EmitInt32(getHeaderSize() + UnitDie.getSize()); + Asm->OutStreamer.AddComment("DWARF version number"); Asm->EmitInt16(DD->getDwarfVersion()); Asm->OutStreamer.AddComment("Offset Into Abbrev. Section"); @@ -1999,50 +1632,9 @@ void DwarfUnit::emitHeader(const MCSymbol *ASectionSym) const { Asm->EmitInt8(Asm->getDataLayout().getPointerSize()); } -void DwarfUnit::addRange(RangeSpan Range) { - // Only add a range for this unit if we're emitting full debug. - if (getCUNode().getEmissionKind() == DIBuilder::FullDebug) { - // If we have no current ranges just add the range and return, otherwise, - // check the current section and CU against the previous section and CU we - // emitted into and the subprogram was contained within. If these are the - // same then extend our current range, otherwise add this as a new range. - if (CURanges.size() == 0 || - this != DD->getPrevCU() || - Asm->getCurrentSection() != DD->getPrevSection()) { - CURanges.push_back(Range); - return; - } - - assert(&(CURanges.back().getEnd()->getSection()) == - &(Range.getEnd()->getSection()) && - "We can only append to a range in the same section!"); - CURanges.back().setEnd(Range.getEnd()); - } -} - -void DwarfCompileUnit::initStmtList(MCSymbol *DwarfLineSectionSym) { - // Define start line table label for each Compile Unit. - MCSymbol *LineTableStartSym = - Asm->OutStreamer.getDwarfLineTableSymbol(getUniqueID()); - - stmtListIndex = UnitDie.getValues().size(); - - // DW_AT_stmt_list is a offset of line number information for this - // compile unit in debug_line section. For split dwarf this is - // left in the skeleton CU and so not included. - // The line table entries are not always emitted in assembly, so it - // is not okay to use line_table_start here. - if (Asm->MAI->doesDwarfUseRelocationsAcrossSections()) - addSectionLabel(UnitDie, dwarf::DW_AT_stmt_list, LineTableStartSym); - else - 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]); +void DwarfUnit::initSection(const MCSection *Section) { + assert(!this->Section); + this->Section = Section; } void DwarfTypeUnit::emitHeader(const MCSymbol *ASectionSym) const { @@ -2055,16 +1647,8 @@ void DwarfTypeUnit::emitHeader(const MCSymbol *ASectionSym) const { sizeof(Ty->getOffset())); } -void DwarfTypeUnit::initSection(const MCSection *Section) { - assert(!this->Section); - this->Section = Section; - // Since each type unit is contained in its own COMDAT section, the begin - // label and the section label are the same. Using the begin label emission in - // DwarfDebug to emit the section label as well is slightly subtle/sneaky, but - // the only other alternative of lazily constructing start-of-section labels - // and storing a mapping in DwarfDebug (or AsmPrinter). - this->SectionSym = this->LabelBegin = - Asm->GetTempSymbol(Section->getLabelBeginName(), getUniqueID()); - this->LabelEnd = - Asm->GetTempSymbol(Section->getLabelEndName(), getUniqueID()); +bool DwarfTypeUnit::isDwoUnit() const { + // Since there are no skeleton type units, all type units are dwo type units + // when split DWARF is being used. + return DD->useSplitDwarf(); } diff --git a/lib/CodeGen/AsmPrinter/DwarfUnit.h b/lib/CodeGen/AsmPrinter/DwarfUnit.h index b7b83b2..f40c937 100644 --- a/lib/CodeGen/AsmPrinter/DwarfUnit.h +++ b/lib/CodeGen/AsmPrinter/DwarfUnit.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef CODEGEN_ASMPRINTER_DWARFCOMPILEUNIT_H -#define CODEGEN_ASMPRINTER_DWARFCOMPILEUNIT_H +#ifndef LLVM_LIB_CODEGEN_ASMPRINTER_DWARFUNIT_H +#define LLVM_LIB_CODEGEN_ASMPRINTER_DWARFUNIT_H #include "DIE.h" #include "DwarfDebug.h" @@ -55,7 +55,8 @@ private: SmallVector<RangeSpan, 2> Ranges; public: - RangeSpanList(MCSymbol *Sym) : RangeSym(Sym) {} + RangeSpanList(MCSymbol *Sym, SmallVector<RangeSpan, 2> Ranges) + : RangeSym(Sym), Ranges(std::move(Ranges)) {} MCSymbol *getSym() const { return RangeSym; } const SmallVectorImpl<RangeSpan> &getRanges() const { return Ranges; } void addRange(RangeSpan Range) { Ranges.push_back(Range); } @@ -96,12 +97,6 @@ protected: /// descriptors to debug information entries using a DIEEntry proxy. DenseMap<const MDNode *, DIEEntry *> MDNodeToDIEEntryMap; - /// GlobalNames - A map of globally visible named entities for this unit. - StringMap<const DIE *> GlobalNames; - - /// GlobalTypes - A map of globally visible types for this unit. - StringMap<const DIE *> GlobalTypes; - /// DIEBlocks - A list of all the DIEBlocks in use. std::vector<DIEBlock *> DIEBlocks; @@ -113,13 +108,6 @@ protected: /// corresponds to the MDNode mapped with the subprogram DIE. DenseMap<DIE *, const MDNode *> ContainingTypeMap; - // List of ranges for a given compile unit. - SmallVector<RangeSpan, 1> CURanges; - - // List of range lists for a given compile unit, separate from the ranges for - // the CU itself. - SmallVector<RangeSpanList, 1> CURangeLists; - // DIEValueAllocator - All DIEValues are allocated through this allocator. BumpPtrAllocator DIEValueAllocator; @@ -129,86 +117,31 @@ protected: /// The section this unit will be emitted in. const MCSection *Section; - /// A label at the start of the non-dwo section related to this unit. - MCSymbol *SectionSym; + DwarfUnit(unsigned UID, dwarf::Tag, DICompileUnit CU, AsmPrinter *A, + DwarfDebug *DW, DwarfFile *DWU); - /// The start of the unit within its section. - MCSymbol *LabelBegin; + void initSection(const MCSection *Section); - /// The end of the unit within its section. - MCSymbol *LabelEnd; + /// Add a string attribute data and value. + void addLocalString(DIE &Die, dwarf::Attribute Attribute, StringRef Str); - /// Skeleton unit associated with this unit. - DwarfUnit *Skeleton; + void addIndexedString(DIE &Die, dwarf::Attribute Attribute, StringRef Str); - DwarfUnit(unsigned UID, dwarf::Tag, DICompileUnit CU, AsmPrinter *A, - DwarfDebug *DW, DwarfFile *DWU); + bool applySubprogramDefinitionAttributes(DISubprogram SP, DIE &SPDie); public: virtual ~DwarfUnit(); - /// Set the skeleton unit associated with this unit. - void setSkeleton(DwarfUnit &Skel) { Skeleton = &Skel; } - - /// Get the skeleton unit associated with this unit. - DwarfUnit *getSkeleton() const { return Skeleton; } - - /// Pass in the SectionSym even though we could recreate it in every compile - /// unit (type units will have actually distinct symbols once they're in - /// comdat sections). - void initSection(const MCSection *Section, MCSymbol *SectionSym) { - assert(!this->Section); - this->Section = Section; - this->SectionSym = SectionSym; - this->LabelBegin = - Asm->GetTempSymbol(Section->getLabelBeginName(), getUniqueID()); - this->LabelEnd = - Asm->GetTempSymbol(Section->getLabelEndName(), getUniqueID()); - } - const MCSection *getSection() const { assert(Section); return Section; } - /// If there's a skeleton then return the section symbol for the skeleton - /// unit, otherwise return the section symbol for this unit. - MCSymbol *getLocalSectionSym() const { - if (Skeleton) - return Skeleton->getSectionSym(); - return getSectionSym(); - } - - MCSymbol *getSectionSym() const { - assert(Section); - return SectionSym; - } - - /// If there's a skeleton then return the begin label for the skeleton unit, - /// otherwise return the local label for this unit. - MCSymbol *getLocalLabelBegin() const { - if (Skeleton) - return Skeleton->getLabelBegin(); - return getLabelBegin(); - } - - MCSymbol *getLabelBegin() const { - assert(Section); - return LabelBegin; - } - - MCSymbol *getLabelEnd() const { - assert(Section); - return LabelEnd; - } - // Accessors. unsigned getUniqueID() const { return UniqueID; } uint16_t getLanguage() const { return CUNode.getLanguage(); } DICompileUnit getCUNode() const { return CUNode; } DIE &getUnitDie() { return UnitDie; } - const StringMap<const DIE *> &getGlobalNames() const { return GlobalNames; } - const StringMap<const DIE *> &getGlobalTypes() const { return GlobalTypes; } unsigned getDebugInfoOffset() const { return DebugInfoOffset; } void setDebugInfoOffset(unsigned DbgInfoOff) { DebugInfoOffset = DbgInfoOff; } @@ -216,29 +149,15 @@ public: /// hasContent - Return true if this compile unit has something to write out. bool hasContent() const { return !UnitDie.getChildren().empty(); } - /// addRange - Add an address range to the list of ranges for this unit. - void addRange(RangeSpan Range); - - /// getRanges - Get the list of ranges for this unit. - const SmallVectorImpl<RangeSpan> &getRanges() const { return CURanges; } - SmallVectorImpl<RangeSpan> &getRanges() { return CURanges; } - - /// addRangeList - Add an address range list to the list of range lists. - void addRangeList(RangeSpanList Ranges) { CURangeLists.push_back(Ranges); } - - /// getRangeLists - Get the vector of range lists. - const SmallVectorImpl<RangeSpanList> &getRangeLists() const { - return CURangeLists; - } - SmallVectorImpl<RangeSpanList> &getRangeLists() { return CURangeLists; } - /// getParentContextString - Get a string containing the language specific /// context for a global name. std::string getParentContextString(DIScope Context) const; - /// addGlobalName - Add a new global entity to the compile unit. - /// - void addGlobalName(StringRef Name, DIE &Die, DIScope Context); + /// Add a new global name to the compile unit. + virtual void addGlobalName(StringRef Name, DIE &Die, DIScope Context) {} + + /// Add a new global type to the compile unit. + virtual void addGlobalType(DIType Ty, const DIE &Die, DIScope Context) {} /// addAccelNamespace - Add a new name to the namespace accelerator table. void addAccelNamespace(StringRef Name, const DIE &Die); @@ -275,14 +194,7 @@ public: void addSInt(DIELoc &Die, Optional<dwarf::Form> Form, int64_t Integer); /// addString - Add a string attribute data and value. - void addString(DIE &Die, dwarf::Attribute Attribute, const StringRef Str); - - /// addLocalString - Add a string attribute data and value. - void addLocalString(DIE &Die, dwarf::Attribute Attribute, - const StringRef Str); - - /// addExpr - Add a Dwarf expression attribute data and value. - void addExpr(DIELoc &Die, dwarf::Form Form, const MCExpr *Expr); + void addString(DIE &Die, dwarf::Attribute Attribute, StringRef Str); /// addLabel - Add a Dwarf label attribute data and value. void addLabel(DIE &Die, dwarf::Attribute Attribute, dwarf::Form Form, @@ -290,14 +202,6 @@ public: 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); - - /// addSectionLabel - Add a Dwarf section label attribute data and value. - /// - 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); @@ -306,10 +210,6 @@ public: /// form given and an op of either DW_FORM_addr or DW_FORM_GNU_addr_index. 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, - const MCSymbol *Lo); - /// addLabelDelta - Add a label delta attribute data and value. void addLabelDelta(DIE &Die, dwarf::Attribute Attribute, const MCSymbol *Hi, const MCSymbol *Lo); @@ -339,11 +239,6 @@ public: 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, - 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, DIType Ty); @@ -359,19 +254,12 @@ public: void addTemplateParams(DIE &Buffer, DIArray TParams); /// addRegisterOp - Add register operand. - void addRegisterOp(DIELoc &TheDie, unsigned Reg); + void addRegisterOpPiece(DIELoc &TheDie, unsigned Reg, + unsigned SizeInBits = 0, unsigned OffsetInBits = 0); /// addRegisterOffset - Add register offset. void addRegisterOffset(DIELoc &TheDie, unsigned Reg, int64_t Offset); - /// addComplexAddress - Start with the address based on the location provided, - /// and generate the DWARF information necessary to find the actual variable - /// (navigating the extra location information encoded in the type) based on - /// the starting location. Add the DWARF information to the die. - void addComplexAddress(const DbgVariable &DV, DIE &Die, - dwarf::Attribute Attribute, - const MachineLocation &Location); - // FIXME: Should be reformulated in terms of addComplexAddress. /// addBlockByrefAddress - Start with the address based on the location /// provided, and generate the DWARF information necessary to find the @@ -382,11 +270,6 @@ public: 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, - 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. @@ -397,11 +280,10 @@ public: DIE *getOrCreateNameSpace(DINameSpace NS); /// getOrCreateSubprogramDIE - Create new DIE using SP. - DIE *getOrCreateSubprogramDIE(DISubprogram SP); + DIE *getOrCreateSubprogramDIE(DISubprogram SP, bool Minimal = false); - void applySubprogramAttributes(DISubprogram SP, DIE &SPDie); - void applySubprogramAttributesToDefinition(DISubprogram SP, DIE &SPDie); - void applyVariableAttributes(const DbgVariable &Var, DIE &VariableDie); + void applySubprogramAttributes(DISubprogram SP, DIE &SPDie, + bool Minimal = false); /// getOrCreateTypeDIE - Find existing DIE or create new DIE for the /// given DIType. @@ -417,12 +299,8 @@ public: /// vtables. void constructContainingTypeDIEs(); - /// constructVariableDIE - Construct a DIE for the given DbgVariable. - std::unique_ptr<DIE> constructVariableDIE(DbgVariable &DV, - bool Abstract = false); - /// constructSubprogramArguments - Construct function argument DIEs. - void constructSubprogramArguments(DIE &Buffer, DIArray Args); + void constructSubprogramArguments(DIE &Buffer, DITypeArray Args); /// Create a DIE with the given Tag, add the DIE to its parent, and /// call insertDIE if MD is not null. @@ -453,12 +331,13 @@ protected: /// none currently exists, create a new ID and insert it in the line table. 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); + /// resolve - Look in the DwarfDebug map for the MDNode that + /// corresponds to the reference. + template <typename T> T resolve(DIRef<T> Ref) const { + return DD->resolve(Ref); + } +private: /// constructTypeDIE - Construct basic type die from DIBasicType. void constructTypeDIE(DIE &Buffer, DIBasicType BTy); @@ -503,7 +382,7 @@ private: } // getIndexTyDie - Get an anonymous type for index type. - DIE *getIndexTyDie() { return IndexTyDie; } + DIE *getIndexTyDie(); // setIndexTyDie - Set D as anonymous type for index which can be reused // later. @@ -513,56 +392,22 @@ private: /// information entry. DIEEntry *createDIEEntry(DIE &Entry); - /// resolve - Look in the DwarfDebug map for the MDNode that - /// corresponds to the reference. - template <typename T> T resolve(DIRef<T> Ref) const { - return DD->resolve(Ref); - } - /// If this is a named finished type then include it in the list of types for /// the accelerator tables. void updateAcceleratorTables(DIScope Context, DIType Ty, const DIE &TyDIE); -}; - -class DwarfCompileUnit : public DwarfUnit { - /// The attribute index of DW_AT_stmt_list in the compile unit DIE, avoiding - /// the need to search for it in applyStmtList. - unsigned stmtListIndex; - -public: - DwarfCompileUnit(unsigned UID, DICompileUnit Node, AsmPrinter *A, - DwarfDebug *DW, DwarfFile *DWU); - - void initStmtList(MCSymbol *DwarfLineSectionSym); - - /// Apply the DW_AT_stmt_list from this compile unit to the specified DIE. - void applyStmtList(DIE &D); - - /// createGlobalVariableDIE - create global variable DIE. - void createGlobalVariableDIE(DIGlobalVariable GV); - - /// addLabelAddress - Add a dwarf label attribute data and value using - /// either DW_FORM_addr or DW_FORM_GNU_addr_index. - void addLabelAddress(DIE &Die, dwarf::Attribute Attribute, - const MCSymbol *Label); - - /// addLocalLabelAddress - Add a dwarf label attribute data and value using - /// DW_FORM_addr only. - void addLocalLabelAddress(DIE &Die, dwarf::Attribute Attribute, - const MCSymbol *Label); - DwarfCompileUnit &getCU() override { return *this; } - - unsigned getOrCreateSourceID(StringRef FileName, StringRef DirName) override; + virtual bool isDwoUnit() const = 0; }; class DwarfTypeUnit : public DwarfUnit { -private: uint64_t TypeSignature; const DIE *Ty; DwarfCompileUnit &CU; MCDwarfDwoLineTable *SplitLineTable; + unsigned getOrCreateSourceID(StringRef File, StringRef Directory) override; + bool isDwoUnit() const override; + public: DwarfTypeUnit(unsigned UID, DwarfCompileUnit &CU, AsmPrinter *A, DwarfDebug *DW, DwarfFile *DWU, @@ -578,11 +423,8 @@ public: return DwarfUnit::getHeaderSize() + sizeof(uint64_t) + // Type Signature sizeof(uint32_t); // Type DIE Offset } - void initSection(const MCSection *Section); + using DwarfUnit::initSection; DwarfCompileUnit &getCU() override { return CU; } - -protected: - unsigned getOrCreateSourceID(StringRef File, StringRef Directory) override; }; } // end llvm namespace #endif diff --git a/lib/CodeGen/AsmPrinter/EHStreamer.cpp b/lib/CodeGen/AsmPrinter/EHStreamer.cpp index 73f62bf..2bbffb3 100644 --- a/lib/CodeGen/AsmPrinter/EHStreamer.cpp +++ b/lib/CodeGen/AsmPrinter/EHStreamer.cpp @@ -237,7 +237,7 @@ computeCallSiteTable(SmallVectorImpl<CallSiteEntry> &CallSites, // instruction between the previous try-range and this one may throw, // create a call-site entry with no landing pad for the region between the // try-ranges. - if (SawPotentiallyThrowing && Asm->MAI->isExceptionHandlingDwarf()) { + if (SawPotentiallyThrowing && Asm->MAI->usesItaniumLSDAForExceptions()) { CallSiteEntry Site = { LastLabel, BeginLabel, nullptr, 0 }; CallSites.push_back(Site); PreviousIsInvoke = false; @@ -259,7 +259,7 @@ computeCallSiteTable(SmallVectorImpl<CallSiteEntry> &CallSites, }; // Try to merge with the previous call-site. SJLJ doesn't do this - if (PreviousIsInvoke && Asm->MAI->isExceptionHandlingDwarf()) { + if (PreviousIsInvoke && Asm->MAI->usesItaniumLSDAForExceptions()) { CallSiteEntry &Prev = CallSites.back(); if (Site.PadLabel == Prev.PadLabel && Site.Action == Prev.Action) { // Extend the range of the previous entry. @@ -269,7 +269,7 @@ computeCallSiteTable(SmallVectorImpl<CallSiteEntry> &CallSites, } // Otherwise, create a new call-site. - if (Asm->MAI->isExceptionHandlingDwarf()) + if (Asm->MAI->usesItaniumLSDAForExceptions()) CallSites.push_back(Site); else { // SjLj EH must maintain the call sites in the order assigned @@ -287,7 +287,7 @@ computeCallSiteTable(SmallVectorImpl<CallSiteEntry> &CallSites, // If some instruction between the previous try-range and the end of the // function may throw, create a call-site entry with no landing pad for the // region following the try-range. - if (SawPotentiallyThrowing && Asm->MAI->isExceptionHandlingDwarf()) { + if (SawPotentiallyThrowing && Asm->MAI->usesItaniumLSDAForExceptions()) { CallSiteEntry Site = { LastLabel, nullptr, nullptr, 0 }; CallSites.push_back(Site); } @@ -314,7 +314,7 @@ computeCallSiteTable(SmallVectorImpl<CallSiteEntry> &CallSites, /// 3. Type ID table contains references to all the C++ typeinfo for all /// catches in the function. This tables is reverse indexed base 1. void EHStreamer::emitExceptionTable() { - const std::vector<const GlobalVariable *> &TypeInfos = MMI->getTypeInfos(); + const std::vector<const GlobalValue *> &TypeInfos = MMI->getTypeInfos(); const std::vector<unsigned> &FilterIds = MMI->getFilterIds(); const std::vector<LandingPadInfo> &PadInfos = MMI->getLandingPads(); @@ -520,7 +520,7 @@ void EHStreamer::emitExceptionTable() { } } else { // DWARF Exception handling - assert(Asm->MAI->isExceptionHandlingDwarf()); + assert(Asm->MAI->usesItaniumLSDAForExceptions()); // The call-site table is a list of all call sites that may throw an // exception (including C++ 'throw' statements) in the procedure @@ -649,7 +649,7 @@ void EHStreamer::emitExceptionTable() { } void EHStreamer::emitTypeInfos(unsigned TTypeEncoding) { - const std::vector<const GlobalVariable *> &TypeInfos = MMI->getTypeInfos(); + const std::vector<const GlobalValue *> &TypeInfos = MMI->getTypeInfos(); const std::vector<unsigned> &FilterIds = MMI->getFilterIds(); bool VerboseAsm = Asm->OutStreamer.isVerboseAsm(); @@ -662,9 +662,9 @@ void EHStreamer::emitTypeInfos(unsigned TTypeEncoding) { Entry = TypeInfos.size(); } - for (std::vector<const GlobalVariable *>::const_reverse_iterator + for (std::vector<const GlobalValue *>::const_reverse_iterator I = TypeInfos.rbegin(), E = TypeInfos.rend(); I != E; ++I) { - const GlobalVariable *GV = *I; + const GlobalValue *GV = *I; if (VerboseAsm) Asm->OutStreamer.AddComment("TypeInfo " + Twine(Entry--)); Asm->EmitTTypeReference(GV, TTypeEncoding); diff --git a/lib/CodeGen/AsmPrinter/EHStreamer.h b/lib/CodeGen/AsmPrinter/EHStreamer.h index 2b6ba78..7e9549d 100644 --- a/lib/CodeGen/AsmPrinter/EHStreamer.h +++ b/lib/CodeGen/AsmPrinter/EHStreamer.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CODEGEN_ASMPRINTER_EHSTREAMER_H -#define LLVM_CODEGEN_ASMPRINTER_EHSTREAMER_H +#ifndef LLVM_LIB_CODEGEN_ASMPRINTER_EHSTREAMER_H +#define LLVM_LIB_CODEGEN_ASMPRINTER_EHSTREAMER_H #include "AsmPrinterHandler.h" #include "llvm/ADT/DenseMap.h" diff --git a/lib/CodeGen/AsmPrinter/ErlangGCPrinter.cpp b/lib/CodeGen/AsmPrinter/ErlangGCPrinter.cpp index bfcbe6b..5bda5a9 100644 --- a/lib/CodeGen/AsmPrinter/ErlangGCPrinter.cpp +++ b/lib/CodeGen/AsmPrinter/ErlangGCPrinter.cpp @@ -28,6 +28,7 @@ #include "llvm/MC/MCSymbol.h" #include "llvm/Target/TargetLoweringObjectFile.h" #include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetSubtargetInfo.h" using namespace llvm; @@ -50,7 +51,8 @@ void ErlangGCPrinter::beginAssembly(AsmPrinter &AP) { } void ErlangGCPrinter::finishAssembly(AsmPrinter &AP) { MCStreamer &OS = AP.OutStreamer; - unsigned IntPtrSize = AP.TM.getDataLayout()->getPointerSize(); + unsigned IntPtrSize = + AP.TM.getSubtargetImpl()->getDataLayout()->getPointerSize(); // Put this in a custom .note section. AP.OutStreamer.SwitchSection(AP.getObjFileLowering().getContext() diff --git a/lib/CodeGen/AsmPrinter/OcamlGCPrinter.cpp b/lib/CodeGen/AsmPrinter/OcamlGCPrinter.cpp index 5a9ecd7..6480d048 100644 --- a/lib/CodeGen/AsmPrinter/OcamlGCPrinter.cpp +++ b/lib/CodeGen/AsmPrinter/OcamlGCPrinter.cpp @@ -26,6 +26,7 @@ #include "llvm/Support/FormattedStream.h" #include "llvm/Target/TargetLoweringObjectFile.h" #include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetSubtargetInfo.h" #include <cctype> using namespace llvm; @@ -91,7 +92,8 @@ void OcamlGCMetadataPrinter::beginAssembly(AsmPrinter &AP) { /// either condition is detected in a function which uses the GC. /// void OcamlGCMetadataPrinter::finishAssembly(AsmPrinter &AP) { - unsigned IntPtrSize = AP.TM.getDataLayout()->getPointerSize(); + unsigned IntPtrSize = + AP.TM.getSubtargetImpl()->getDataLayout()->getPointerSize(); AP.OutStreamer.SwitchSection(AP.getObjFileLowering().getTextSection()); EmitCamlGlobal(getModule(), AP, "code_end"); diff --git a/lib/CodeGen/AsmPrinter/Win64Exception.cpp b/lib/CodeGen/AsmPrinter/Win64Exception.cpp index 81285d5..0f0ad75 100644 --- a/lib/CodeGen/AsmPrinter/Win64Exception.cpp +++ b/lib/CodeGen/AsmPrinter/Win64Exception.cpp @@ -11,7 +11,7 @@ // //===----------------------------------------------------------------------===// -#include "DwarfException.h" +#include "Win64Exception.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/Twine.h" diff --git a/lib/CodeGen/AsmPrinter/Win64Exception.h b/lib/CodeGen/AsmPrinter/Win64Exception.h new file mode 100644 index 0000000..538e132 --- /dev/null +++ b/lib/CodeGen/AsmPrinter/Win64Exception.h @@ -0,0 +1,52 @@ +//===-- Win64Exception.h - Windows Exception Handling ----------*- C++ -*--===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains support for writing windows exception info into asm files. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_CODEGEN_ASMPRINTER_WIN64EXCEPTION_H +#define LLVM_LIB_CODEGEN_ASMPRINTER_WIN64EXCEPTION_H + +#include "EHStreamer.h" + +namespace llvm { +class MachineFunction; + +class Win64Exception : public EHStreamer { + /// Per-function flag to indicate if personality info should be emitted. + bool shouldEmitPersonality; + + /// Per-function flag to indicate if the LSDA should be emitted. + bool shouldEmitLSDA; + + /// Per-function flag to indicate if frame moves info should be emitted. + bool shouldEmitMoves; + +public: + //===--------------------------------------------------------------------===// + // Main entry points. + // + Win64Exception(AsmPrinter *A); + virtual ~Win64Exception(); + + /// Emit all exception information that should come after the content. + void endModule() override; + + /// Gather pre-function exception information. Assumes being emitted + /// immediately after the function entry point. + void beginFunction(const MachineFunction *MF) override; + + /// Gather and emit post-function exception information. + void endFunction(const MachineFunction *) override; +}; +} + +#endif + diff --git a/lib/CodeGen/AsmPrinter/WinCodeViewLineTables.cpp b/lib/CodeGen/AsmPrinter/WinCodeViewLineTables.cpp index 6a5c431..b5e0929 100644 --- a/lib/CodeGen/AsmPrinter/WinCodeViewLineTables.cpp +++ b/lib/CodeGen/AsmPrinter/WinCodeViewLineTables.cpp @@ -116,15 +116,67 @@ WinCodeViewLineTables::WinCodeViewLineTables(AsmPrinter *AP) Asm = AP; } +void WinCodeViewLineTables::endModule() { + if (FnDebugInfo.empty()) + return; + + assert(Asm != nullptr); + Asm->OutStreamer.SwitchSection( + Asm->getObjFileLowering().getCOFFDebugSymbolsSection()); + Asm->EmitInt32(COFF::DEBUG_SECTION_MAGIC); + + // The COFF .debug$S section consists of several subsections, each starting + // with a 4-byte control code (e.g. 0xF1, 0xF2, etc) and then a 4-byte length + // of the payload followed by the payload itself. The subsections are 4-byte + // aligned. + + // Emit per-function debug information. This code is extracted into a + // separate function for readability. + for (size_t I = 0, E = VisitedFunctions.size(); I != E; ++I) + emitDebugInfoForFunction(VisitedFunctions[I]); + + // This subsection holds a file index to offset in string table table. + Asm->OutStreamer.AddComment("File index to string table offset subsection"); + Asm->EmitInt32(COFF::DEBUG_INDEX_SUBSECTION); + size_t NumFilenames = FileNameRegistry.Infos.size(); + Asm->EmitInt32(8 * NumFilenames); + for (size_t I = 0, E = FileNameRegistry.Filenames.size(); I != E; ++I) { + StringRef Filename = FileNameRegistry.Filenames[I]; + // For each unique filename, just write its offset in the string table. + Asm->EmitInt32(FileNameRegistry.Infos[Filename].StartOffset); + // The function name offset is not followed by any additional data. + Asm->EmitInt32(0); + } + + // This subsection holds the string table. + Asm->OutStreamer.AddComment("String table"); + Asm->EmitInt32(COFF::DEBUG_STRING_TABLE_SUBSECTION); + Asm->EmitInt32(FileNameRegistry.LastOffset); + // The payload starts with a null character. + Asm->EmitInt8(0); + + for (size_t I = 0, E = FileNameRegistry.Filenames.size(); I != E; ++I) { + // Just emit unique filenames one by one, separated by a null character. + Asm->OutStreamer.EmitBytes(FileNameRegistry.Filenames[I]); + Asm->EmitInt8(0); + } + + // No more subsections. Fill with zeros to align the end of the section by 4. + Asm->OutStreamer.EmitFill((-FileNameRegistry.LastOffset) % 4, 0); + + clear(); +} + static void EmitLabelDiff(MCStreamer &Streamer, - const MCSymbol *From, const MCSymbol *To) { + const MCSymbol *From, const MCSymbol *To, + unsigned int Size = 4) { MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None; MCContext &Context = Streamer.getContext(); const MCExpr *FromRef = MCSymbolRefExpr::Create(From, Variant, Context), *ToRef = MCSymbolRefExpr::Create(To, Variant, Context); const MCExpr *AddrDelta = MCBinaryExpr::Create(MCBinaryExpr::Sub, ToRef, FromRef, Context); - Streamer.EmitValue(AddrDelta, 4); + Streamer.EmitValue(AddrDelta, Size); } void WinCodeViewLineTables::emitDebugInfoForFunction(const Function *GV) { @@ -138,6 +190,51 @@ void WinCodeViewLineTables::emitDebugInfoForFunction(const Function *GV) { return; assert(FI.End && "Don't know where the function ends?"); + StringRef FuncName = getDISubprogram(GV).getDisplayName(), + GVName = GV->getName(); + // FIXME Clang currently sets DisplayName to "bar" for a C++ + // "namespace_foo::bar" function, see PR21528. Luckily, dbghelp.dll is trying + // to demangle display names anyways, so let's just put a mangled name into + // the symbols subsection until Clang gives us what we need. + if (GVName.startswith("\01?")) + FuncName = GVName.substr(1); + // Emit a symbol subsection, required by VS2012+ to find function boundaries. + MCSymbol *SymbolsBegin = Asm->MMI->getContext().CreateTempSymbol(), + *SymbolsEnd = Asm->MMI->getContext().CreateTempSymbol(); + Asm->OutStreamer.AddComment("Symbol subsection for " + Twine(FuncName)); + Asm->EmitInt32(COFF::DEBUG_SYMBOL_SUBSECTION); + EmitLabelDiff(Asm->OutStreamer, SymbolsBegin, SymbolsEnd); + Asm->OutStreamer.EmitLabel(SymbolsBegin); + { + MCSymbol *ProcSegmentBegin = Asm->MMI->getContext().CreateTempSymbol(), + *ProcSegmentEnd = Asm->MMI->getContext().CreateTempSymbol(); + EmitLabelDiff(Asm->OutStreamer, ProcSegmentBegin, ProcSegmentEnd, 2); + Asm->OutStreamer.EmitLabel(ProcSegmentBegin); + + Asm->EmitInt16(COFF::DEBUG_SYMBOL_TYPE_PROC_START); + // Some bytes of this segment don't seem to be required for basic debugging, + // so just fill them with zeroes. + Asm->OutStreamer.EmitFill(12, 0); + // This is the important bit that tells the debugger where the function + // code is located and what's its size: + EmitLabelDiff(Asm->OutStreamer, Fn, FI.End); + Asm->OutStreamer.EmitFill(12, 0); + Asm->OutStreamer.EmitCOFFSecRel32(Fn); + Asm->OutStreamer.EmitCOFFSectionIndex(Fn); + Asm->EmitInt8(0); + // Emit the function display name as a null-terminated string. + Asm->OutStreamer.EmitBytes(FuncName); + Asm->EmitInt8(0); + Asm->OutStreamer.EmitLabel(ProcSegmentEnd); + + // We're done with this function. + Asm->EmitInt16(0x0002); + Asm->EmitInt16(COFF::DEBUG_SYMBOL_TYPE_PROC_END); + } + Asm->OutStreamer.EmitLabel(SymbolsEnd); + // Every subsection must be aligned to a 4-byte boundary. + Asm->OutStreamer.EmitFill((-FuncName.size()) % 4, 0); + // PCs/Instructions are grouped into segments sharing the same filename. // Pre-calculate the lengths (in instructions) of these segments and store // them in a map for convenience. Each index in the map is the sequential @@ -154,18 +251,19 @@ void WinCodeViewLineTables::emitDebugInfoForFunction(const Function *GV) { } FilenameSegmentLengths[LastSegmentEnd] = FI.Instrs.size() - LastSegmentEnd; - // Emit the control code of the subsection followed by the payload size. - Asm->OutStreamer.AddComment( - "Linetable subsection for " + Twine(Fn->getName())); + // Emit a line table subsection, requred to do PC-to-file:line lookup. + Asm->OutStreamer.AddComment("Line table subsection for " + Twine(FuncName)); Asm->EmitInt32(COFF::DEBUG_LINE_TABLE_SUBSECTION); - MCSymbol *SubsectionBegin = Asm->MMI->getContext().CreateTempSymbol(), - *SubsectionEnd = Asm->MMI->getContext().CreateTempSymbol(); - EmitLabelDiff(Asm->OutStreamer, SubsectionBegin, SubsectionEnd); - Asm->OutStreamer.EmitLabel(SubsectionBegin); + MCSymbol *LineTableBegin = Asm->MMI->getContext().CreateTempSymbol(), + *LineTableEnd = Asm->MMI->getContext().CreateTempSymbol(); + EmitLabelDiff(Asm->OutStreamer, LineTableBegin, LineTableEnd); + Asm->OutStreamer.EmitLabel(LineTableBegin); // Identify the function this subsection is for. Asm->OutStreamer.EmitCOFFSecRel32(Fn); Asm->OutStreamer.EmitCOFFSectionIndex(Fn); + // Insert padding after a 16-bit section index. + Asm->EmitInt16(0); // Length of the function's code, in bytes. EmitLabelDiff(Asm->OutStreamer, Fn, FI.End); @@ -209,56 +307,7 @@ void WinCodeViewLineTables::emitDebugInfoForFunction(const Function *GV) { if (FileSegmentEnd) Asm->OutStreamer.EmitLabel(FileSegmentEnd); - Asm->OutStreamer.EmitLabel(SubsectionEnd); -} - -void WinCodeViewLineTables::endModule() { - if (FnDebugInfo.empty()) - return; - - assert(Asm != nullptr); - Asm->OutStreamer.SwitchSection( - Asm->getObjFileLowering().getCOFFDebugSymbolsSection()); - Asm->EmitInt32(COFF::DEBUG_SECTION_MAGIC); - - // The COFF .debug$S section consists of several subsections, each starting - // with a 4-byte control code (e.g. 0xF1, 0xF2, etc) and then a 4-byte length - // of the payload followed by the payload itself. The subsections are 4-byte - // aligned. - - for (size_t I = 0, E = VisitedFunctions.size(); I != E; ++I) - emitDebugInfoForFunction(VisitedFunctions[I]); - - // This subsection holds a file index to offset in string table table. - Asm->OutStreamer.AddComment("File index to string table offset subsection"); - Asm->EmitInt32(COFF::DEBUG_INDEX_SUBSECTION); - size_t NumFilenames = FileNameRegistry.Infos.size(); - Asm->EmitInt32(8 * NumFilenames); - for (size_t I = 0, E = FileNameRegistry.Filenames.size(); I != E; ++I) { - StringRef Filename = FileNameRegistry.Filenames[I]; - // For each unique filename, just write it's offset in the string table. - Asm->EmitInt32(FileNameRegistry.Infos[Filename].StartOffset); - // The function name offset is not followed by any additional data. - Asm->EmitInt32(0); - } - - // This subsection holds the string table. - Asm->OutStreamer.AddComment("String table"); - Asm->EmitInt32(COFF::DEBUG_STRING_TABLE_SUBSECTION); - Asm->EmitInt32(FileNameRegistry.LastOffset); - // The payload starts with a null character. - Asm->EmitInt8(0); - - for (size_t I = 0, E = FileNameRegistry.Filenames.size(); I != E; ++I) { - // Just emit unique filenames one by one, separated by a null character. - Asm->OutStreamer.EmitBytes(FileNameRegistry.Filenames[I]); - Asm->EmitInt8(0); - } - - // No more subsections. Fill with zeros to align the end of the section by 4. - Asm->OutStreamer.EmitFill((-FileNameRegistry.LastOffset) % 4, 0); - - clear(); + Asm->OutStreamer.EmitLabel(LineTableEnd); } void WinCodeViewLineTables::beginFunction(const MachineFunction *MF) { diff --git a/lib/CodeGen/AsmPrinter/WinCodeViewLineTables.h b/lib/CodeGen/AsmPrinter/WinCodeViewLineTables.h index 0734d97..8492eac 100644 --- a/lib/CodeGen/AsmPrinter/WinCodeViewLineTables.h +++ b/lib/CodeGen/AsmPrinter/WinCodeViewLineTables.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef CODEGEN_ASMPRINTER_WINCODEVIEWLINETABLES_H__ -#define CODEGEN_ASMPRINTER_WINCODEVIEWLINETABLES_H__ +#ifndef LLVM_LIB_CODEGEN_ASMPRINTER_WINCODEVIEWLINETABLES_H +#define LLVM_LIB_CODEGEN_ASMPRINTER_WINCODEVIEWLINETABLES_H #include "AsmPrinterHandler.h" #include "llvm/ADT/DenseMap.h" |