diff options
author | Stephen Hines <srhines@google.com> | 2014-04-23 16:57:46 -0700 |
---|---|---|
committer | Stephen Hines <srhines@google.com> | 2014-04-24 15:53:16 -0700 |
commit | 36b56886974eae4f9c5ebc96befd3e7bfe5de338 (patch) | |
tree | e6cfb69fbbd937f450eeb83bfb83b9da3b01275a /lib/CodeGen/AsmPrinter | |
parent | 69a8640022b04415ae9fac62f8ab090601d8f889 (diff) | |
download | external_llvm-36b56886974eae4f9c5ebc96befd3e7bfe5de338.tar.gz external_llvm-36b56886974eae4f9c5ebc96befd3e7bfe5de338.tar.bz2 external_llvm-36b56886974eae4f9c5ebc96befd3e7bfe5de338.zip |
Update to LLVM 3.5a.
Change-Id: Ifadecab779f128e62e430c2b4f6ddd84953ed617
Diffstat (limited to 'lib/CodeGen/AsmPrinter')
29 files changed, 4157 insertions, 2779 deletions
diff --git a/lib/CodeGen/AsmPrinter/ARMException.cpp b/lib/CodeGen/AsmPrinter/ARMException.cpp index 5d82dd9e9a..403feb4583 100644 --- a/lib/CodeGen/AsmPrinter/ARMException.cpp +++ b/lib/CodeGen/AsmPrinter/ARMException.cpp @@ -20,6 +20,7 @@ #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/IR/DataLayout.h" +#include "llvm/IR/Mangler.h" #include "llvm/IR/Module.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCContext.h" @@ -30,43 +31,52 @@ #include "llvm/Support/CommandLine.h" #include "llvm/Support/Dwarf.h" #include "llvm/Support/FormattedStream.h" -#include "llvm/Target/Mangler.h" #include "llvm/Target/TargetFrameLowering.h" #include "llvm/Target/TargetOptions.h" #include "llvm/Target/TargetRegisterInfo.h" using namespace llvm; -static cl::opt<bool> -EnableARMEHABIDescriptors("arm-enable-ehabi-descriptors", cl::Hidden, - cl::desc("Generate ARM EHABI tables with unwinding descriptors"), - cl::init(false)); - - ARMException::ARMException(AsmPrinter *A) - : DwarfException(A) {} + : DwarfException(A), + shouldEmitCFI(false) {} ARMException::~ARMException() {} ARMTargetStreamer &ARMException::getTargetStreamer() { - MCTargetStreamer &TS = Asm->OutStreamer.getTargetStreamer(); + MCTargetStreamer &TS = *Asm->OutStreamer.getTargetStreamer(); return static_cast<ARMTargetStreamer &>(TS); } -void ARMException::EndModule() { +/// endModule - Emit all exception information that should come after the +/// content. +void ARMException::endModule() { + if (shouldEmitCFI) + Asm->OutStreamer.EmitCFISections(false, true); } -/// BeginFunction - Gather pre-function exception information. Assumes it's +/// beginFunction - Gather pre-function exception information. Assumes it's /// being emitted immediately after the function entry point. -void ARMException::BeginFunction(const MachineFunction *MF) { +void ARMException::beginFunction(const MachineFunction *MF) { getTargetStreamer().emitFnStart(); if (Asm->MF->getFunction()->needsUnwindTableEntry()) Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("eh_func_begin", Asm->getFunctionNumber())); + // See if we need call frame info. + AsmPrinter::CFIMoveType MoveType = Asm->needsCFIMoves(); + assert(MoveType != AsmPrinter::CFI_M_EH && + "non-EH CFI not yet supported in prologue with EHABI lowering"); + if (MoveType == AsmPrinter::CFI_M_Debug) { + shouldEmitCFI = true; + Asm->OutStreamer.EmitCFIStartProc(false); + } } -/// EndFunction - Gather and emit post-function exception information. +/// endFunction - Gather and emit post-function exception information. /// -void ARMException::EndFunction() { +void ARMException::endFunction(const MachineFunction *) { + if (shouldEmitCFI) + Asm->OutStreamer.EmitCFIEndProc(); + ARMTargetStreamer &ATS = getTargetStreamer(); if (!Asm->MF->getFunction()->needsUnwindTableEntry()) ATS.emitCantUnwind(); @@ -74,25 +84,23 @@ void ARMException::EndFunction() { Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("eh_func_end", Asm->getFunctionNumber())); - if (EnableARMEHABIDescriptors) { - // Map all labels and get rid of any dead landing pads. - MMI->TidyLandingPads(); + // Map all labels and get rid of any dead landing pads. + MMI->TidyLandingPads(); - if (!MMI->getLandingPads().empty()) { - // Emit references to personality. - if (const Function * Personality = - MMI->getPersonalities()[MMI->getPersonalityIndex()]) { - MCSymbol *PerSym = Asm->getSymbol(Personality); - Asm->OutStreamer.EmitSymbolAttribute(PerSym, MCSA_Global); - ATS.emitPersonality(PerSym); - } + if (!MMI->getLandingPads().empty()) { + // Emit references to personality. + if (const Function * Personality = + MMI->getPersonalities()[MMI->getPersonalityIndex()]) { + MCSymbol *PerSym = Asm->getSymbol(Personality); + Asm->OutStreamer.EmitSymbolAttribute(PerSym, MCSA_Global); + ATS.emitPersonality(PerSym); + } - // Emit .handlerdata directive. - ATS.emitHandlerData(); + // Emit .handlerdata directive. + ATS.emitHandlerData(); - // Emit actual exception table - EmitExceptionTable(); - } + // Emit actual exception table + EmitExceptionTable(); } } diff --git a/lib/CodeGen/AsmPrinter/Android.mk b/lib/CodeGen/AsmPrinter/Android.mk index b2cc47eb92..a725fba2c0 100644 --- a/lib/CodeGen/AsmPrinter/Android.mk +++ b/lib/CodeGen/AsmPrinter/Android.mk @@ -16,12 +16,13 @@ LOCAL_SRC_FILES := \ DIEHash.cpp \ DwarfAccelTable.cpp \ DwarfCFIException.cpp \ - DwarfCompileUnit.cpp \ DwarfDebug.cpp \ DwarfException.cpp \ + DwarfUnit.cpp \ ErlangGCPrinter.cpp \ OcamlGCPrinter.cpp \ - Win64Exception.cpp + Win64Exception.cpp \ + WinCodeViewLineTables.cpp LOCAL_MODULE:= libLLVMAsmPrinter @@ -33,6 +34,7 @@ include $(BUILD_HOST_STATIC_LIBRARY) # For the device # ===================================================== +ifneq (true,$(DISABLE_LLVM_DEVICE_BUILDS)) include $(CLEAR_VARS) LOCAL_SRC_FILES := \ @@ -44,12 +46,13 @@ LOCAL_SRC_FILES := \ DIEHash.cpp \ DwarfAccelTable.cpp \ DwarfCFIException.cpp \ - DwarfCompileUnit.cpp \ DwarfDebug.cpp \ DwarfException.cpp \ + DwarfUnit.cpp \ ErlangGCPrinter.cpp \ + OcamlGCPrinter.cpp \ Win64Exception.cpp \ - $(LOCAL_SRC_FILES) + WinCodeViewLineTables.cpp LOCAL_MODULE:= libLLVMAsmPrinter @@ -58,3 +61,4 @@ LOCAL_MODULE_TAGS := optional include $(LLVM_DEVICE_BUILD_MK) include $(LLVM_GEN_INTRINSICS_MK) include $(BUILD_STATIC_LIBRARY) +endif diff --git a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp index 308b0e091a..c3afc8ba8c 100644 --- a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -15,19 +15,21 @@ #include "llvm/CodeGen/AsmPrinter.h" #include "DwarfDebug.h" #include "DwarfException.h" +#include "WinCodeViewLineTables.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/Statistic.h" #include "llvm/Analysis/ConstantFolding.h" -#include "llvm/Assembly/Writer.h" #include "llvm/CodeGen/GCMetadataPrinter.h" #include "llvm/CodeGen/MachineConstantPool.h" #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineInstrBundle.h" #include "llvm/CodeGen/MachineJumpTableInfo.h" #include "llvm/CodeGen/MachineLoopInfo.h" #include "llvm/CodeGen/MachineModuleInfo.h" -#include "llvm/DebugInfo.h" #include "llvm/IR/DataLayout.h" +#include "llvm/IR/DebugInfo.h" +#include "llvm/IR/Mangler.h" #include "llvm/IR/Module.h" #include "llvm/IR/Operator.h" #include "llvm/MC/MCAsmInfo.h" @@ -41,19 +43,20 @@ #include "llvm/Support/Format.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/Timer.h" -#include "llvm/Target/Mangler.h" #include "llvm/Target/TargetFrameLowering.h" #include "llvm/Target/TargetInstrInfo.h" #include "llvm/Target/TargetLowering.h" #include "llvm/Target/TargetLoweringObjectFile.h" #include "llvm/Target/TargetOptions.h" #include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Target/TargetSubtargetInfo.h" #include "llvm/Transforms/Utils/GlobalStatus.h" using namespace llvm; static const char *const DWARFGroupName = "DWARF Emission"; -static const char *const DbgTimerName = "DWARF Debug Writer"; +static const char *const DbgTimerName = "Debug Info Emission"; static const char *const EHTimerName = "DWARF Exception Writer"; +static const char *const CodeViewLineTablesGroupName = "CodeView Line Tables"; STATISTIC(EmittedInsts, "Number of machine instrs printed"); @@ -99,14 +102,14 @@ AsmPrinter::AsmPrinter(TargetMachine &tm, MCStreamer &Streamer) OutContext(Streamer.getContext()), OutStreamer(Streamer), LastMI(0), LastFn(0), Counter(~0U), SetCounter(0) { - DD = 0; DE = 0; MMI = 0; LI = 0; MF = 0; + DD = 0; MMI = 0; LI = 0; MF = 0; CurrentFnSym = CurrentFnSymForSize = 0; GCMetadataPrinters = 0; VerboseAsm = Streamer.isVerboseAsm(); } AsmPrinter::~AsmPrinter() { - assert(DD == 0 && DE == 0 && "Debug/EH info didn't get finalized"); + assert(DD == 0 && Handlers.empty() && "Debug/EH info didn't get finalized"); if (GCMetadataPrinters != 0) { gcp_map_type &GCMap = getGCMap(GCMetadataPrinters); @@ -135,6 +138,14 @@ const DataLayout &AsmPrinter::getDataLayout() const { return *TM.getDataLayout(); } +const MCSubtargetInfo &AsmPrinter::getSubtargetInfo() const { + return TM.getSubtarget<MCSubtargetInfo>(); +} + +void AsmPrinter::EmitToStreamer(MCStreamer &S, const MCInst &Inst) { + S.EmitInstruction(Inst, getSubtargetInfo()); +} + StringRef AsmPrinter::getTargetTriple() const { return TM.getTargetTriple(); } @@ -163,9 +174,28 @@ bool AsmPrinter::doInitialization(Module &M) { const_cast<TargetLoweringObjectFile&>(getObjFileLowering()) .Initialize(OutContext, TM); - OutStreamer.InitStreamer(); + OutStreamer.InitSections(); - Mang = new Mangler(&TM); + Mang = new Mangler(TM.getDataLayout()); + + // Emit the version-min deplyment target directive if needed. + // + // FIXME: If we end up with a collection of these sorts of Darwin-specific + // or ELF-specific things, it may make sense to have a platform helper class + // that will work with the target helper class. For now keep it here, as the + // alternative is duplicated code in each of the target asm printers that + // use the directive, where it would need the same conditionalization + // anyway. + Triple TT(getTargetTriple()); + if (TT.isOSDarwin()) { + unsigned Major, Minor, Update; + TT.getOSVersion(Major, Minor, Update); + // If there is a version specified, Major will be non-zero. + if (Major) + OutStreamer.EmitVersionMin((TT.isMacOSX() ? + MCVM_OSXVersionMin : MCVM_IOSVersionMin), + Major, Minor, Update); + } // Allow the target to emit any magic that it wants at the start of the file. EmitStartOfAsmFile(M); @@ -192,25 +222,65 @@ bool AsmPrinter::doInitialization(Module &M) { OutStreamer.AddBlankLine(); } - if (MAI->doesSupportDebugInformation()) - DD = new DwarfDebug(this, &M); + if (MAI->doesSupportDebugInformation()) { + if (Triple(TM.getTargetTriple()).isKnownWindowsMSVCEnvironment()) { + Handlers.push_back(HandlerInfo(new WinCodeViewLineTables(this), + DbgTimerName, + CodeViewLineTablesGroupName)); + } else { + DD = new DwarfDebug(this, &M); + Handlers.push_back(HandlerInfo(DD, DbgTimerName, DWARFGroupName)); + } + } + DwarfException *DE = 0; switch (MAI->getExceptionHandlingType()) { case ExceptionHandling::None: - return false; + break; case ExceptionHandling::SjLj: case ExceptionHandling::DwarfCFI: DE = new DwarfCFIException(this); - return false; + break; case ExceptionHandling::ARM: DE = new ARMException(this); - return false; + break; case ExceptionHandling::Win64: DE = new Win64Exception(this); + break; + } + if (DE) + Handlers.push_back(HandlerInfo(DE, EHTimerName, DWARFGroupName)); + return false; +} + +static bool canBeHidden(const GlobalValue *GV, const MCAsmInfo &MAI) { + GlobalValue::LinkageTypes Linkage = GV->getLinkage(); + if (Linkage != GlobalValue::LinkOnceODRLinkage) + return false; + + if (!MAI.hasWeakDefCanBeHiddenDirective()) + return false; + + if (GV->hasUnnamedAddr()) + return true; + + // This is only used for MachO, so right now it doesn't really matter how + // we handle alias. Revisit this once the MachO linker implements aliases. + if (isa<GlobalAlias>(GV)) return false; + + // If it is a non constant variable, it needs to be uniqued across shared + // objects. + if (const GlobalVariable *Var = dyn_cast<GlobalVariable>(GV)) { + if (!Var->isConstant()) + return false; } - llvm_unreachable("Unknown exception type."); + GlobalStatus GS; + if (!GlobalStatus::analyzeGlobal(GV, GS) && !GS.IsCompared) + return true; + + return false; } void AsmPrinter::EmitLinkage(const GlobalValue *GV, MCSymbol *GVSym) const { @@ -221,29 +291,16 @@ void AsmPrinter::EmitLinkage(const GlobalValue *GV, MCSymbol *GVSym) const { case GlobalValue::LinkOnceODRLinkage: case GlobalValue::WeakAnyLinkage: case GlobalValue::WeakODRLinkage: - case GlobalValue::LinkerPrivateWeakLinkage: - if (MAI->getWeakDefDirective() != 0) { + if (MAI->hasWeakDefDirective()) { // .globl _foo OutStreamer.EmitSymbolAttribute(GVSym, MCSA_Global); - bool CanBeHidden = false; - - if (Linkage == GlobalValue::LinkOnceODRLinkage) { - if (GV->hasUnnamedAddr()) { - CanBeHidden = true; - } else { - GlobalStatus GS; - if (!GlobalStatus::analyzeGlobal(GV, GS) && !GS.IsCompared) - CanBeHidden = true; - } - } - - if (!CanBeHidden) + if (!canBeHidden(GV, *MAI)) // .weak_definition _foo OutStreamer.EmitSymbolAttribute(GVSym, MCSA_WeakDefinition); else OutStreamer.EmitSymbolAttribute(GVSym, MCSA_WeakDefAutoPrivate); - } else if (MAI->getLinkOnceDirective() != 0) { + } else if (MAI->hasLinkOnceDirective()) { // .globl _foo OutStreamer.EmitSymbolAttribute(GVSym, MCSA_Global); //NOTE: linkonce is handled by the section the symbol was assigned to. @@ -252,7 +309,6 @@ void AsmPrinter::EmitLinkage(const GlobalValue *GV, MCSymbol *GVSym) const { OutStreamer.EmitSymbolAttribute(GVSym, MCSA_Weak); } return; - case GlobalValue::DLLExportLinkage: case GlobalValue::AppendingLinkage: // FIXME: appending linkage variables should go into a section of // their name or something. For now, just emit them as external. @@ -263,19 +319,22 @@ void AsmPrinter::EmitLinkage(const GlobalValue *GV, MCSymbol *GVSym) const { return; case GlobalValue::PrivateLinkage: case GlobalValue::InternalLinkage: - case GlobalValue::LinkerPrivateLinkage: return; case GlobalValue::AvailableExternallyLinkage: llvm_unreachable("Should never emit this"); - case GlobalValue::DLLImportLinkage: case GlobalValue::ExternalWeakLinkage: llvm_unreachable("Don't know how to emit these"); } llvm_unreachable("Unknown linkage type!"); } +void AsmPrinter::getNameWithPrefix(SmallVectorImpl<char> &Name, + const GlobalValue *GV) const { + TM.getNameWithPrefix(Name, GV, *Mang); +} + MCSymbol *AsmPrinter::getSymbol(const GlobalValue *GV) const { - return getObjFileLowering().getSymbol(*Mang, GV); + return TM.getSymbol(GV, *Mang); } /// EmitGlobalVariable - Emit the specified global variable to the .s file. @@ -286,7 +345,7 @@ void AsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) { return; if (isVerbose()) { - WriteAsOperand(OutStreamer.GetCommentOS(), GV, + GV->printAsOperand(OutStreamer.GetCommentOS(), /*PrintType=*/false, GV->getParent()); OutStreamer.GetCommentOS() << '\n'; } @@ -311,8 +370,11 @@ void AsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) { // sections and expected to be contiguous (e.g. ObjC metadata). unsigned AlignLog = getGVAlignmentLog2(GV, *DL); - if (DD) - DD->setSymbolSize(GVSym, Size); + for (unsigned I = 0, E = Handlers.size(); I != E; ++I) { + const HandlerInfo &OI = Handlers[I]; + NamedRegionTimer T(OI.TimerName, OI.TimerGroupName, TimePassesIsEnabled); + OI.Handler->setSymbolSize(GVSym, Size); + } // Handle common and BSS local symbols (.lcomm). if (GVKind.isCommon() || GVKind.isBSSLocal()) { @@ -332,7 +394,7 @@ void AsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) { // Handle local BSS symbols. if (MAI->hasMachoZeroFillDirective()) { const MCSection *TheSection = - getObjFileLowering().SectionForGlobal(GV, GVKind, Mang, TM); + getObjFileLowering().SectionForGlobal(GV, GVKind, *Mang, TM); // .zerofill __DATA, __bss, _foo, 400, 5 OutStreamer.EmitZerofill(TheSection, GVSym, Size, Align); return; @@ -361,7 +423,7 @@ void AsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) { } const MCSection *TheSection = - getObjFileLowering().SectionForGlobal(GV, GVKind, Mang, TM); + getObjFileLowering().SectionForGlobal(GV, GVKind, *Mang, TM); // Handle the zerofill directive on darwin, which is a special form of BSS // emission. @@ -452,7 +514,8 @@ void AsmPrinter::EmitFunctionHeader() { // Print the 'header' of function. const Function *F = MF->getFunction(); - OutStreamer.SwitchSection(getObjFileLowering().SectionForGlobal(F, Mang, TM)); + OutStreamer.SwitchSection( + getObjFileLowering().SectionForGlobal(F, *Mang, TM)); EmitVisibility(CurrentFnSym, F->getVisibility()); EmitLinkage(F, CurrentFnSym); @@ -462,7 +525,7 @@ void AsmPrinter::EmitFunctionHeader() { OutStreamer.EmitSymbolAttribute(CurrentFnSym, MCSA_ELF_TypeFunction); if (isVerbose()) { - WriteAsOperand(OutStreamer.GetCommentOS(), F, + F->printAsOperand(OutStreamer.GetCommentOS(), /*PrintType=*/false, F->getParent()); OutStreamer.GetCommentOS() << '\n'; } @@ -482,13 +545,10 @@ void AsmPrinter::EmitFunctionHeader() { } // Emit pre-function debug and/or EH information. - if (DE) { - NamedRegionTimer T(EHTimerName, DWARFGroupName, TimePassesIsEnabled); - DE->BeginFunction(MF); - } - if (DD) { - NamedRegionTimer T(DbgTimerName, DWARFGroupName, TimePassesIsEnabled); - DD->beginFunction(MF); + for (unsigned I = 0, E = Handlers.size(); I != E; ++I) { + const HandlerInfo &OI = Handlers[I]; + NamedRegionTimer T(OI.TimerName, OI.TimerGroupName, TimePassesIsEnabled); + OI.Handler->beginFunction(MF); } // Emit the prefix data. @@ -576,10 +636,9 @@ static bool emitDebugValueComment(const MachineInstr *MI, AsmPrinter &AP) { SmallString<128> Str; raw_svector_ostream OS(Str); - OS << '\t' << AP.MAI->getCommentString() << "DEBUG_VALUE: "; + OS << "DEBUG_VALUE: "; - // cast away const; DIetc do not take const operands for some reason. - DIVariable V(const_cast<MDNode*>(MI->getOperand(2).getMetadata())); + DIVariable V(MI->getOperand(2).getMetadata()); if (V.getContext().isSubprogram()) { StringRef Name = DISubprogram(V.getContext()).getDisplayName(); if (!Name.empty()) @@ -625,7 +684,7 @@ static bool emitDebugValueComment(const MachineInstr *MI, AsmPrinter &AP) { // Suppress offset, it is not meaningful here. OS << "undef"; // NOTE: Want this comment at start of line, don't emit with AddComment. - AP.OutStreamer.EmitRawText(OS.str()); + AP.OutStreamer.emitRawComment(OS.str()); return true; } if (Deref) @@ -637,7 +696,7 @@ static bool emitDebugValueComment(const MachineInstr *MI, AsmPrinter &AP) { OS << '+' << Offset << ']'; // NOTE: Want this comment at start of line, don't emit with AddComment. - AP.OutStreamer.EmitRawText(OS.str()); + AP.OutStreamer.emitRawComment(OS.str()); return true; } @@ -657,14 +716,11 @@ bool AsmPrinter::needsSEHMoves() { MF->getFunction()->needsUnwindTableEntry(); } -bool AsmPrinter::needsRelocationsForDwarfStringPool() const { - return MAI->doesDwarfUseRelocationsAcrossSections(); -} - -void AsmPrinter::emitPrologLabel(const MachineInstr &MI) { - const MCSymbol *Label = MI.getOperand(0).getMCSymbol(); - - if (MAI->getExceptionHandlingType() != ExceptionHandling::DwarfCFI) +void AsmPrinter::emitCFIInstruction(const MachineInstr &MI) { + ExceptionHandling::ExceptionsType ExceptionHandlingType = + MAI->getExceptionHandlingType(); + if (ExceptionHandlingType != ExceptionHandling::DwarfCFI && + ExceptionHandlingType != ExceptionHandling::ARM) return; if (needsCFIMoves() == CFI_M_None) @@ -675,16 +731,9 @@ void AsmPrinter::emitPrologLabel(const MachineInstr &MI) { const MachineModuleInfo &MMI = MF->getMMI(); const std::vector<MCCFIInstruction> &Instrs = MMI.getFrameInstructions(); - bool FoundOne = false; - (void)FoundOne; - for (std::vector<MCCFIInstruction>::const_iterator I = Instrs.begin(), - E = Instrs.end(); I != E; ++I) { - if (I->getLabel() == Label) { - emitCFIInstruction(*I); - FoundOne = true; - } - } - assert(FoundOne); + unsigned CFIIndex = MI.getOperand(0).getCFIIndex(); + const MCCFIInstruction &CFI = Instrs[CFIIndex]; + emitCFIInstruction(CFI); } /// EmitFunctionBody - This method emits the body and trailer for a @@ -693,7 +742,7 @@ void AsmPrinter::EmitFunctionBody() { // Emit target-specific gunk before the function body. EmitFunctionBodyStart(); - bool ShouldPrintDebugScopes = DD && MMI->hasDebugInfo(); + bool ShouldPrintDebugScopes = MMI->hasDebugInfo(); // Print out code for the function. bool HasAnyRealCode = false; @@ -707,23 +756,27 @@ void AsmPrinter::EmitFunctionBody() { LastMI = II; // Print the assembly for the instruction. - if (!II->isLabel() && !II->isImplicitDef() && !II->isKill() && + if (!II->isPosition() && !II->isImplicitDef() && !II->isKill() && !II->isDebugValue()) { HasAnyRealCode = true; ++EmittedInsts; } if (ShouldPrintDebugScopes) { - NamedRegionTimer T(DbgTimerName, DWARFGroupName, TimePassesIsEnabled); - DD->beginInstruction(II); + for (unsigned III = 0, EEE = Handlers.size(); III != EEE; ++III) { + const HandlerInfo &OI = Handlers[III]; + NamedRegionTimer T(OI.TimerName, OI.TimerGroupName, + TimePassesIsEnabled); + OI.Handler->beginInstruction(II); + } } if (isVerbose()) emitComments(*II, OutStreamer.GetCommentOS()); switch (II->getOpcode()) { - case TargetOpcode::PROLOG_LABEL: - emitPrologLabel(*II); + case TargetOpcode::CFI_INSTRUCTION: + emitCFIInstruction(*II); break; case TargetOpcode::EH_LABEL: @@ -746,16 +799,17 @@ void AsmPrinter::EmitFunctionBody() { if (isVerbose()) emitKill(II, *this); break; default: - if (!TM.hasMCUseLoc()) - MCLineEntry::Make(&OutStreamer, getCurrentSection()); - EmitInstruction(II); break; } if (ShouldPrintDebugScopes) { - NamedRegionTimer T(DbgTimerName, DWARFGroupName, TimePassesIsEnabled); - DD->endInstruction(II); + for (unsigned III = 0, EEE = Handlers.size(); III != EEE; ++III) { + const HandlerInfo &OI = Handlers[III]; + NamedRegionTimer T(OI.TimerName, OI.TimerGroupName, + TimePassesIsEnabled); + OI.Handler->endInstruction(); + } } } } @@ -765,7 +819,7 @@ void AsmPrinter::EmitFunctionBody() { // label equaling the end of function label and an invalid "row" in the // FDE. We need to emit a noop in this situation so that the FDE's rows are // valid. - bool RequiresNoop = LastMI && LastMI->isPrologLabel(); + bool RequiresNoop = LastMI && LastMI->isCFIInstruction(); // If the function is empty and the object file uses .subsections_via_symbols, // then we need to emit *something* to the function body to prevent the @@ -775,7 +829,7 @@ void AsmPrinter::EmitFunctionBody() { TM.getInstrInfo()->getNoopForMachoTarget(Noop); if (Noop.getOpcode()) { OutStreamer.AddComment("avoids zero-length function"); - OutStreamer.EmitInstruction(Noop); + OutStreamer.EmitInstruction(Noop, getSubtargetInfo()); } else // Target not mc-ized yet. OutStreamer.EmitRawText(StringRef("\tnop\n")); } @@ -811,14 +865,11 @@ void AsmPrinter::EmitFunctionBody() { OutStreamer.EmitELFSize(CurrentFnSym, SizeExp); } - // Emit post-function debug information. - if (DD) { - NamedRegionTimer T(DbgTimerName, DWARFGroupName, TimePassesIsEnabled); - DD->endFunction(MF); - } - if (DE) { - NamedRegionTimer T(EHTimerName, DWARFGroupName, TimePassesIsEnabled); - DE->EndFunction(); + // Emit post-function debug and/or EH information. + for (unsigned I = 0, E = Handlers.size(); I != E; ++I) { + const HandlerInfo &OI = Handlers[I]; + NamedRegionTimer T(OI.TimerName, OI.TimerGroupName, TimePassesIsEnabled); + OI.Handler->endFunction(MF); } MMI->EndFunction(); @@ -828,56 +879,6 @@ void AsmPrinter::EmitFunctionBody() { OutStreamer.AddBlankLine(); } -/// EmitDwarfRegOp - Emit dwarf register operation. -void AsmPrinter::EmitDwarfRegOp(const MachineLocation &MLoc, - bool Indirect) const { - const TargetRegisterInfo *TRI = TM.getRegisterInfo(); - int Reg = TRI->getDwarfRegNum(MLoc.getReg(), false); - - for (MCSuperRegIterator SR(MLoc.getReg(), TRI); SR.isValid() && Reg < 0; - ++SR) { - Reg = TRI->getDwarfRegNum(*SR, false); - // FIXME: Get the bit range this register uses of the superregister - // so that we can produce a DW_OP_bit_piece - } - - // FIXME: Handle cases like a super register being encoded as - // DW_OP_reg 32 DW_OP_piece 4 DW_OP_reg 33 - - // FIXME: We have no reasonable way of handling errors in here. The - // caller might be in the middle of an dwarf expression. We should - // probably assert that Reg >= 0 once debug info generation is more mature. - - if (MLoc.isIndirect() || Indirect) { - if (Reg < 32) { - OutStreamer.AddComment( - dwarf::OperationEncodingString(dwarf::DW_OP_breg0 + Reg)); - EmitInt8(dwarf::DW_OP_breg0 + Reg); - } else { - OutStreamer.AddComment("DW_OP_bregx"); - EmitInt8(dwarf::DW_OP_bregx); - OutStreamer.AddComment(Twine(Reg)); - EmitULEB128(Reg); - } - EmitSLEB128(!MLoc.isIndirect() ? 0 : MLoc.getOffset()); - if (MLoc.isIndirect() && Indirect) - EmitInt8(dwarf::DW_OP_deref); - } else { - if (Reg < 32) { - OutStreamer.AddComment( - dwarf::OperationEncodingString(dwarf::DW_OP_reg0 + Reg)); - EmitInt8(dwarf::DW_OP_reg0 + Reg); - } else { - OutStreamer.AddComment("DW_OP_regx"); - EmitInt8(dwarf::DW_OP_regx); - OutStreamer.AddComment(Twine(Reg)); - EmitULEB128(Reg); - } - } - - // FIXME: Produce a DW_OP_bit_piece if we used a superregister -} - bool AsmPrinter::doFinalization(Module &M) { // Emit global variables. for (Module::const_global_iterator I = M.global_begin(), E = M.global_end(); @@ -901,26 +902,21 @@ bool AsmPrinter::doFinalization(Module &M) { SmallVector<Module::ModuleFlagEntry, 8> ModuleFlags; M.getModuleFlagsMetadata(ModuleFlags); if (!ModuleFlags.empty()) - getObjFileLowering().emitModuleFlags(OutStreamer, ModuleFlags, Mang, TM); + getObjFileLowering().emitModuleFlags(OutStreamer, ModuleFlags, *Mang, TM); // Make sure we wrote out everything we need. OutStreamer.Flush(); // Finalize debug and EH information. - if (DE) { - { - NamedRegionTimer T(EHTimerName, DWARFGroupName, TimePassesIsEnabled); - DE->EndModule(); - } - delete DE; DE = 0; - } - if (DD) { - { - NamedRegionTimer T(DbgTimerName, DWARFGroupName, TimePassesIsEnabled); - DD->endModule(); - } - delete DD; DD = 0; + for (unsigned I = 0, E = Handlers.size(); I != E; ++I) { + const HandlerInfo &OI = Handlers[I]; + NamedRegionTimer T(OI.TimerName, OI.TimerGroupName, + TimePassesIsEnabled); + OI.Handler->endModule(); + delete OI.Handler; } + Handlers.clear(); + DD = 0; // If the target wants to know about weak references, print them all. if (MAI->getWeakRefDirective()) { @@ -949,11 +945,7 @@ bool AsmPrinter::doFinalization(Module &M) { MCSymbol *Name = getSymbol(I); const GlobalValue *GV = I->getAliasedGlobal(); - if (GV->isDeclaration()) { - report_fatal_error(Name->getName() + - ": Target doesn't support aliases to declarations"); - } - + assert(!GV->isDeclaration()); MCSymbol *Target = getSymbol(GV); if (I->hasExternalLinkage() || !MAI->getWeakRefDirective()) @@ -1106,6 +1098,7 @@ void AsmPrinter::EmitConstantPool() { /// by the current function to the current output stream. /// void AsmPrinter::EmitJumpTableInfo() { + const DataLayout *DL = MF->getTarget().getDataLayout(); const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo(); if (MJTI == 0) return; if (MJTI->getEntryKind() == MachineJumpTableInfo::EK_Inline) return; @@ -1125,7 +1118,8 @@ void AsmPrinter::EmitJumpTableInfo() { // FIXME: this isn't the right predicate, should be based on the MCSection // for the function. F->isWeakForLinker()) { - OutStreamer.SwitchSection(getObjFileLowering().SectionForGlobal(F,Mang,TM)); + OutStreamer.SwitchSection( + getObjFileLowering().SectionForGlobal(F, *Mang, TM)); } else { // Otherwise, drop it in the readonly section. const MCSection *ReadOnlySection = @@ -1171,7 +1165,7 @@ void AsmPrinter::EmitJumpTableInfo() { // before each jump table. The first label is never referenced, but tells // the assembler and linker the extents of the jump table object. The // second label is actually referenced by the code. - if (JTInDiffSection && MAI->getLinkerPrivateGlobalPrefix()[0]) + if (JTInDiffSection && DL->hasLinkerPrivateGlobalPrefix()) // FIXME: This doesn't have to have any specific name, just any randomly // named and numbered 'l' label would work. Simplify GetJTISymbol. OutStreamer.EmitLabel(GetJTISymbol(JTI, true)); @@ -1309,7 +1303,7 @@ void AsmPrinter::EmitLLVMUsedList(const ConstantArray *InitList) { for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) { const GlobalValue *GV = dyn_cast<GlobalValue>(InitList->getOperand(i)->stripPointerCasts()); - if (GV && getObjFileLowering().shouldEmitUsedDirectiveFor(GV, Mang)) + if (GV) OutStreamer.EmitSymbolAttribute(getSymbol(GV), MCSA_NoDeadStrip); } } @@ -1366,7 +1360,7 @@ void AsmPrinter::EmitModuleIdents(Module &M) { if (const NamedMDNode *NMD = M.getNamedMetadata("llvm.ident")) { for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) { const MDNode *N = NMD->getOperand(i); - assert(N->getNumOperands() == 1 && + assert(N->getNumOperands() == 1 && "llvm.ident metadata entry can have only one operand"); const MDString *S = cast<MDString>(N->getOperand(0)); OutStreamer.EmitIdent(S->getString()); @@ -1422,8 +1416,8 @@ void AsmPrinter::EmitLabelDifference(const MCSymbol *Hi, const MCSymbol *Lo, /// where the size in bytes of the directive is specified by Size and Hi/Lo /// specify the labels. This implicitly uses .set if it is available. void AsmPrinter::EmitLabelOffsetDifference(const MCSymbol *Hi, uint64_t Offset, - const MCSymbol *Lo, unsigned Size) - const { + const MCSymbol *Lo, + unsigned Size) const { // Emit Hi+Offset - Lo // Get the Hi+Offset expression. @@ -1452,8 +1446,8 @@ void AsmPrinter::EmitLabelOffsetDifference(const MCSymbol *Hi, uint64_t Offset, /// where the size in bytes of the directive is specified by Size and Label /// specifies the label. This implicitly uses .set if it is available. void AsmPrinter::EmitLabelPlusOffset(const MCSymbol *Label, uint64_t Offset, - unsigned Size, bool IsSectionRelative) - const { + unsigned Size, + bool IsSectionRelative) const { if (MAI->needsDwarfSectionOffsetDirective() && IsSectionRelative) { OutStreamer.EmitCOFFSecRel32(Label); return; @@ -1462,14 +1456,12 @@ void AsmPrinter::EmitLabelPlusOffset(const MCSymbol *Label, uint64_t Offset, // Emit Label+Offset (or just Label if Offset is zero) const MCExpr *Expr = MCSymbolRefExpr::Create(Label, OutContext); if (Offset) - Expr = MCBinaryExpr::CreateAdd(Expr, - MCConstantExpr::Create(Offset, OutContext), - OutContext); + Expr = MCBinaryExpr::CreateAdd( + Expr, MCConstantExpr::Create(Offset, OutContext), OutContext); OutStreamer.EmitValue(Expr, Size); } - //===----------------------------------------------------------------------===// // EmitAlignment - Emit an alignment directive to the specified power of @@ -1486,7 +1478,7 @@ void AsmPrinter::EmitAlignment(unsigned NumBits, const GlobalValue *GV) const { if (getCurrentSection()->getKind().isText()) OutStreamer.EmitCodeAlignment(1 << NumBits); else - OutStreamer.EmitValueToAlignment(1 << NumBits, 0, 1, 0); + OutStreamer.EmitValueToAlignment(1 << NumBits); } //===----------------------------------------------------------------------===// @@ -1515,6 +1507,11 @@ static const MCExpr *lowerConstant(const Constant *CV, AsmPrinter &AP) { llvm_unreachable("Unknown constant value to lower!"); } + if (const MCExpr *RelocExpr = + AP.getObjFileLowering().getExecutableRelativeSymbol(CE, *AP.Mang, + AP.TM)) + return RelocExpr; + switch (CE->getOpcode()) { default: // If the code isn't optimized, there may be outstanding folding @@ -1530,7 +1527,7 @@ static const MCExpr *lowerConstant(const Constant *CV, AsmPrinter &AP) { std::string S; raw_string_ostream OS(S); OS << "Unsupported expression in static initializer: "; - WriteAsOperand(OS, CE, /*PrintType=*/false, + CE->printAsOperand(OS, /*PrintType=*/false, !AP.MF ? 0 : AP.MF->getFunction()->getParent()); report_fatal_error(OS.str()); } @@ -1994,15 +1991,17 @@ void AsmPrinter::printOffset(int64_t Offset, raw_ostream &OS) const { /// GetTempSymbol - Return the MCSymbol corresponding to the assembler /// temporary label with the specified stem and unique ID. -MCSymbol *AsmPrinter::GetTempSymbol(StringRef Name, unsigned ID) const { - return OutContext.GetOrCreateSymbol(Twine(MAI->getPrivateGlobalPrefix()) + +MCSymbol *AsmPrinter::GetTempSymbol(Twine Name, unsigned ID) const { + const DataLayout *DL = TM.getDataLayout(); + return OutContext.GetOrCreateSymbol(Twine(DL->getPrivateGlobalPrefix()) + Name + Twine(ID)); } /// GetTempSymbol - Return an assembler temporary label with the specified /// stem. -MCSymbol *AsmPrinter::GetTempSymbol(StringRef Name) const { - return OutContext.GetOrCreateSymbol(Twine(MAI->getPrivateGlobalPrefix())+ +MCSymbol *AsmPrinter::GetTempSymbol(Twine Name) const { + const DataLayout *DL = TM.getDataLayout(); + return OutContext.GetOrCreateSymbol(Twine(DL->getPrivateGlobalPrefix())+ Name); } @@ -2017,8 +2016,9 @@ MCSymbol *AsmPrinter::GetBlockAddressSymbol(const BasicBlock *BB) const { /// GetCPISymbol - Return the symbol for the specified constant pool entry. MCSymbol *AsmPrinter::GetCPISymbol(unsigned CPID) const { + const DataLayout *DL = TM.getDataLayout(); return OutContext.GetOrCreateSymbol - (Twine(MAI->getPrivateGlobalPrefix()) + "CPI" + Twine(getFunctionNumber()) + (Twine(DL->getPrivateGlobalPrefix()) + "CPI" + Twine(getFunctionNumber()) + "_" + Twine(CPID)); } @@ -2030,21 +2030,16 @@ MCSymbol *AsmPrinter::GetJTISymbol(unsigned JTID, bool isLinkerPrivate) const { /// GetJTSetSymbol - Return the symbol for the specified jump table .set /// FIXME: privatize to AsmPrinter. MCSymbol *AsmPrinter::GetJTSetSymbol(unsigned UID, unsigned MBBID) const { + const DataLayout *DL = TM.getDataLayout(); return OutContext.GetOrCreateSymbol - (Twine(MAI->getPrivateGlobalPrefix()) + Twine(getFunctionNumber()) + "_" + + (Twine(DL->getPrivateGlobalPrefix()) + Twine(getFunctionNumber()) + "_" + Twine(UID) + "_set_" + Twine(MBBID)); } -/// GetSymbolWithGlobalValueBase - Return the MCSymbol for a symbol with -/// global value name as its base, with the specified suffix, and where the -/// symbol is forced to have private linkage if ForcePrivate is true. -MCSymbol *AsmPrinter::GetSymbolWithGlobalValueBase(const GlobalValue *GV, - StringRef Suffix, - bool ForcePrivate) const { - SmallString<60> NameStr; - Mang->getNameWithPrefix(NameStr, GV, ForcePrivate); - NameStr.append(Suffix.begin(), Suffix.end()); - return OutContext.GetOrCreateSymbol(NameStr.str()); +MCSymbol *AsmPrinter::getSymbolWithGlobalValueBase(const GlobalValue *GV, + StringRef Suffix) const { + return getObjFileLowering().getSymbolWithGlobalValueBase(GV, Suffix, *Mang, + TM); } /// GetExternalSymbolSymbol - Return the MCSymbol for the specified @@ -2155,10 +2150,9 @@ void AsmPrinter::EmitBasicBlockStart(const MachineBasicBlock *MBB) const { // Print the main label for the block. if (MBB->pred_empty() || isBlockOnlyReachableByFallthrough(MBB)) { - if (isVerbose() && OutStreamer.hasRawTextSupport()) { + if (isVerbose()) { // NOTE: Want this comment at start of line, don't emit with AddComment. - OutStreamer.EmitRawText(Twine(MAI->getCommentString()) + " BB#" + - Twine(MBB->getNumber()) + ":"); + OutStreamer.emitRawComment(" BB#" + Twine(MBB->getNumber()) + ":", false); } } else { OutStreamer.EmitLabel(MBB->getSymbol()); @@ -2221,14 +2215,13 @@ isBlockOnlyReachableByFallthrough(const MachineBasicBlock *MBB) const { if (!MI.isBranch() || MI.isIndirectBranch()) return false; - // If we are the operands of one of the branches, this is not - // a fall through. - for (MachineInstr::mop_iterator OI = MI.operands_begin(), - OE = MI.operands_end(); OI != OE; ++OI) { - const MachineOperand& OP = *OI; - if (OP.isJTI()) + // If we are the operands of one of the branches, this is not a fall + // through. Note that targets with delay slots will usually bundle + // terminators with the delay slot instruction. + for (ConstMIBundleOperands OP(&MI); OP.isValid(); ++OP) { + if (OP->isJTI()) return false; - if (OP.isMBB() && OP.getMBB() == MBB) + if (OP->isMBB() && OP->getMBB() == MBB) return false; } } @@ -2261,3 +2254,6 @@ GCMetadataPrinter *AsmPrinter::GetOrCreateGCPrinter(GCStrategy *S) { report_fatal_error("no GCMetadataPrinter registered for GC: " + Twine(Name)); } + +/// Pin vtable to this file. +AsmPrinterHandler::~AsmPrinterHandler() {} diff --git a/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp b/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp index b92f49cfae..b696069562 100644 --- a/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp +++ b/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp @@ -12,7 +12,9 @@ //===----------------------------------------------------------------------===// #define DEBUG_TYPE "asm-printer" +#include "ByteStreamer.h" #include "llvm/CodeGen/AsmPrinter.h" +#include "llvm/ADT/SmallBitVector.h" #include "llvm/ADT/Twine.h" #include "llvm/IR/DataLayout.h" #include "llvm/MC/MCAsmInfo.h" @@ -52,9 +54,9 @@ void AsmPrinter::EmitULEB128(uint64_t Value, const char *Desc, /// EmitCFAByte - Emit a .byte 42 directive for a DW_CFA_xxx value. void AsmPrinter::EmitCFAByte(unsigned Val) const { if (isVerbose()) { - if (Val >= dwarf::DW_CFA_offset && Val < dwarf::DW_CFA_offset+64) + if (Val >= dwarf::DW_CFA_offset && Val < dwarf::DW_CFA_offset + 64) OutStreamer.AddComment("DW_CFA_offset + Reg (" + - Twine(Val-dwarf::DW_CFA_offset) + ")"); + Twine(Val - dwarf::DW_CFA_offset) + ")"); else OutStreamer.AddComment(dwarf::CallFrameString(Val)); } @@ -63,43 +65,56 @@ void AsmPrinter::EmitCFAByte(unsigned Val) const { static const char *DecodeDWARFEncoding(unsigned Encoding) { switch (Encoding) { - case dwarf::DW_EH_PE_absptr: return "absptr"; - case dwarf::DW_EH_PE_omit: return "omit"; - case dwarf::DW_EH_PE_pcrel: return "pcrel"; - case dwarf::DW_EH_PE_udata4: return "udata4"; - case dwarf::DW_EH_PE_udata8: return "udata8"; - case dwarf::DW_EH_PE_sdata4: return "sdata4"; - case dwarf::DW_EH_PE_sdata8: return "sdata8"; - case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_udata4: return "pcrel udata4"; - case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4: return "pcrel sdata4"; - case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_udata8: return "pcrel udata8"; - case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata8: return "pcrel sdata8"; - case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |dwarf::DW_EH_PE_udata4: + case dwarf::DW_EH_PE_absptr: + return "absptr"; + case dwarf::DW_EH_PE_omit: + return "omit"; + case dwarf::DW_EH_PE_pcrel: + return "pcrel"; + case dwarf::DW_EH_PE_udata4: + return "udata4"; + case dwarf::DW_EH_PE_udata8: + return "udata8"; + case dwarf::DW_EH_PE_sdata4: + return "sdata4"; + case dwarf::DW_EH_PE_sdata8: + return "sdata8"; + case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_udata4: + return "pcrel udata4"; + case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4: + return "pcrel sdata4"; + case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_udata8: + return "pcrel udata8"; + case dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata8: + return "pcrel sdata8"; + case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_udata4 + : return "indirect pcrel udata4"; - case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |dwarf::DW_EH_PE_sdata4: + case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4 + : return "indirect pcrel sdata4"; - case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |dwarf::DW_EH_PE_udata8: + case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_udata8 + : return "indirect pcrel udata8"; - case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel |dwarf::DW_EH_PE_sdata8: + case dwarf::DW_EH_PE_indirect | dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata8 + : return "indirect pcrel sdata8"; } return "<unknown encoding>"; } - /// EmitEncodingByte - Emit a .byte 42 directive that corresponds to an /// encoding. If verbose assembly output is enabled, we output comments /// describing the encoding. Desc is an optional string saying what the /// encoding is specifying (e.g. "LSDA"). void AsmPrinter::EmitEncodingByte(unsigned Val, const char *Desc) const { if (isVerbose()) { - if (Desc != 0) - OutStreamer.AddComment(Twine(Desc)+" Encoding = " + + if (Desc) + OutStreamer.AddComment(Twine(Desc) + " Encoding = " + Twine(DecodeDWARFEncoding(Val))); else - OutStreamer.AddComment(Twine("Encoding = ") + - DecodeDWARFEncoding(Val)); + OutStreamer.AddComment(Twine("Encoding = ") + DecodeDWARFEncoding(Val)); } OutStreamer.EmitIntValue(Val, 1); @@ -111,11 +126,16 @@ unsigned AsmPrinter::GetSizeOfEncodedValue(unsigned Encoding) const { return 0; switch (Encoding & 0x07) { - default: llvm_unreachable("Invalid encoded value."); - case dwarf::DW_EH_PE_absptr: return TM.getDataLayout()->getPointerSize(); - case dwarf::DW_EH_PE_udata2: return 2; - case dwarf::DW_EH_PE_udata4: return 4; - case dwarf::DW_EH_PE_udata8: return 8; + default: + llvm_unreachable("Invalid encoded value."); + case dwarf::DW_EH_PE_absptr: + return TM.getDataLayout()->getPointerSize(); + case dwarf::DW_EH_PE_udata2: + return 2; + case dwarf::DW_EH_PE_udata4: + return 4; + case dwarf::DW_EH_PE_udata8: + return 8; } } @@ -125,7 +145,7 @@ void AsmPrinter::EmitTTypeReference(const GlobalValue *GV, const TargetLoweringObjectFile &TLOF = getObjFileLowering(); const MCExpr *Exp = - TLOF.getTTypeGlobalReference(GV, Mang, MMI, Encoding, OutStreamer); + TLOF.getTTypeGlobalReference(GV, Encoding, *Mang, TM, MMI, OutStreamer); OutStreamer.EmitValue(Exp, GetSizeOfEncodedValue(Encoding)); } else OutStreamer.EmitIntValue(0, GetSizeOfEncodedValue(Encoding)); @@ -165,6 +185,150 @@ void AsmPrinter::EmitSectionOffset(const MCSymbol *Label, EmitLabelDifference(Label, SectionLabel, 4); } +/// Emit a dwarf register operation. +static void emitDwarfRegOp(ByteStreamer &Streamer, int Reg) { + assert(Reg >= 0); + if (Reg < 32) { + Streamer.EmitInt8(dwarf::DW_OP_reg0 + Reg, + dwarf::OperationEncodingString(dwarf::DW_OP_reg0 + Reg)); + } else { + Streamer.EmitInt8(dwarf::DW_OP_regx, "DW_OP_regx"); + Streamer.EmitULEB128(Reg, Twine(Reg)); + } +} + +/// Emit an (double-)indirect dwarf register operation. +static void emitDwarfRegOpIndirect(ByteStreamer &Streamer, int Reg, int Offset, + bool Deref) { + assert(Reg >= 0); + if (Reg < 32) { + Streamer.EmitInt8(dwarf::DW_OP_breg0 + Reg, + dwarf::OperationEncodingString(dwarf::DW_OP_breg0 + Reg)); + } else { + Streamer.EmitInt8(dwarf::DW_OP_bregx, "DW_OP_bregx"); + Streamer.EmitULEB128(Reg, Twine(Reg)); + } + Streamer.EmitSLEB128(Offset); + if (Deref) + Streamer.EmitInt8(dwarf::DW_OP_deref, "DW_OP_deref"); +} + +/// Emit a dwarf register operation for describing +/// - a small value occupying only part of a register or +/// - a small register representing only part of a value. +static void emitDwarfOpPiece(ByteStreamer &Streamer, unsigned Size, + unsigned Offset) { + assert(Size > 0); + if (Offset > 0) { + Streamer.EmitInt8(dwarf::DW_OP_bit_piece, "DW_OP_bit_piece"); + Streamer.EmitULEB128(Size, Twine(Size)); + Streamer.EmitULEB128(Offset, Twine(Offset)); + } else { + Streamer.EmitInt8(dwarf::DW_OP_piece, "DW_OP_piece"); + unsigned ByteSize = Size / 8; // Assuming 8 bits per byte. + Streamer.EmitULEB128(ByteSize, Twine(ByteSize)); + } +} + +/// Some targets do not provide a DWARF register number for every +/// register. This function attempts to emit a dwarf register by +/// emitting a piece of a super-register or by piecing together +/// multiple subregisters that alias the register. +static void EmitDwarfRegOpPiece(ByteStreamer &Streamer, const AsmPrinter &AP, + const MachineLocation &MLoc) { + assert(!MLoc.isIndirect()); + const TargetRegisterInfo *TRI = AP.TM.getRegisterInfo(); + int Reg = TRI->getDwarfRegNum(MLoc.getReg(), false); + + // Walk up the super-register chain until we find a valid number. + // For example, EAX on x86_64 is a 32-bit piece of RAX with offset 0. + for (MCSuperRegIterator SR(MLoc.getReg(), TRI); SR.isValid(); ++SR) { + Reg = TRI->getDwarfRegNum(*SR, false); + if (Reg >= 0) { + unsigned Idx = TRI->getSubRegIndex(*SR, MLoc.getReg()); + unsigned Size = TRI->getSubRegIdxSize(Idx); + unsigned Offset = TRI->getSubRegIdxOffset(Idx); + AP.OutStreamer.AddComment("super-register"); + emitDwarfRegOp(Streamer, Reg); + emitDwarfOpPiece(Streamer, Size, Offset); + return; + } + } + + // Otherwise, attempt to find a covering set of sub-register numbers. + // For example, Q0 on ARM is a composition of D0+D1. + // + // Keep track of the current position so we can emit the more + // efficient DW_OP_piece. + unsigned CurPos = 0; + // The size of the register in bits, assuming 8 bits per byte. + unsigned RegSize = TRI->getMinimalPhysRegClass(MLoc.getReg())->getSize() * 8; + // Keep track of the bits in the register we already emitted, so we + // can avoid emitting redundant aliasing subregs. + SmallBitVector Coverage(RegSize, false); + for (MCSubRegIterator SR(MLoc.getReg(), TRI); SR.isValid(); ++SR) { + unsigned Idx = TRI->getSubRegIndex(MLoc.getReg(), *SR); + unsigned Size = TRI->getSubRegIdxSize(Idx); + unsigned Offset = TRI->getSubRegIdxOffset(Idx); + Reg = TRI->getDwarfRegNum(*SR, false); + + // Intersection between the bits we already emitted and the bits + // covered by this subregister. + SmallBitVector Intersection(RegSize, false); + Intersection.set(Offset, Offset + Size); + Intersection ^= Coverage; + + // If this sub-register has a DWARF number and we haven't covered + // its range, emit a DWARF piece for it. + if (Reg >= 0 && Intersection.any()) { + AP.OutStreamer.AddComment("sub-register"); + emitDwarfRegOp(Streamer, Reg); + emitDwarfOpPiece(Streamer, Size, Offset == CurPos ? 0 : Offset); + CurPos = Offset + Size; + + // Mark it as emitted. + Coverage.set(Offset, Offset + Size); + } + } + + if (CurPos == 0) { + // FIXME: We have no reasonable way of handling errors in here. + Streamer.EmitInt8(dwarf::DW_OP_nop, + "nop (could not find a dwarf register number)"); + } +} + +/// EmitDwarfRegOp - Emit dwarf register operation. +void AsmPrinter::EmitDwarfRegOp(ByteStreamer &Streamer, + const MachineLocation &MLoc, + bool Indirect) const { + const TargetRegisterInfo *TRI = TM.getRegisterInfo(); + int Reg = TRI->getDwarfRegNum(MLoc.getReg(), false); + if (Reg < 0) { + // We assume that pointers are always in an addressable register. + if (Indirect || MLoc.isIndirect()) { + // FIXME: We have no reasonable way of handling errors in here. The + // caller might be in the middle of a dwarf expression. We should + // probably assert that Reg >= 0 once debug info generation is more + // mature. + Streamer.EmitInt8(dwarf::DW_OP_nop, + "nop (invalid dwarf register number for indirect loc)"); + return; + } + + // Attempt to find a valid super- or sub-register. + if (!Indirect && !MLoc.isIndirect()) + return EmitDwarfRegOpPiece(Streamer, *this, MLoc); + } + + if (MLoc.isIndirect()) + emitDwarfRegOpIndirect(Streamer, Reg, MLoc.getOffset(), Indirect); + else if (Indirect) + emitDwarfRegOpIndirect(Streamer, Reg, 0, false); + else + emitDwarfRegOp(Streamer, Reg); +} + //===----------------------------------------------------------------------===// // Dwarf Lowering Routines //===----------------------------------------------------------------------===// @@ -191,5 +355,8 @@ void AsmPrinter::emitCFIInstruction(const MCCFIInstruction &Inst) const { case MCCFIInstruction::OpWindowSave: OutStreamer.EmitCFIWindowSave(); break; + case MCCFIInstruction::OpSameValue: + OutStreamer.EmitCFISameValue(Inst.getRegister()); + break; } } diff --git a/lib/CodeGen/AsmPrinter/AsmPrinterHandler.h b/lib/CodeGen/AsmPrinter/AsmPrinterHandler.h new file mode 100644 index 0000000000..2825367abd --- /dev/null +++ b/lib/CodeGen/AsmPrinter/AsmPrinterHandler.h @@ -0,0 +1,57 @@ +//===-- lib/CodeGen/AsmPrinter/AsmPrinterHandler.h -------------*- C++ -*--===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains a generic interface for AsmPrinter handlers, +// like debug and EH info emitters. +// +//===----------------------------------------------------------------------===// + +#ifndef CODEGEN_ASMPRINTER_ASMPRINTERHANDLER_H__ +#define CODEGEN_ASMPRINTER_ASMPRINTERHANDLER_H__ + +#include "llvm/Support/DataTypes.h" + +namespace llvm { + +class MachineFunction; +class MachineInstr; +class MCSymbol; + +/// \brief Collects and handles AsmPrinter objects required to build debug +/// or EH information. +class AsmPrinterHandler { +public: + virtual ~AsmPrinterHandler(); + + /// \brief For symbols that have a size designated (e.g. common symbols), + /// this tracks that size. + virtual void setSymbolSize(const MCSymbol *Sym, uint64_t Size) = 0; + + /// \brief Emit all sections that should come after the content. + virtual void endModule() = 0; + + /// \brief Gather pre-function debug information. + /// Every beginFunction(MF) call should be followed by an endFunction(MF) + /// call. + virtual void beginFunction(const MachineFunction *MF) = 0; + + /// \brief Gather post-function debug information. + /// Please note that some AsmPrinter implementations may not call + /// beginFunction at all. + virtual void endFunction(const MachineFunction *MF) = 0; + + /// \brief Process beginning of an instruction. + virtual void beginInstruction(const MachineInstr *MI) = 0; + + /// \brief Process end of an instruction. + virtual void endInstruction() = 0; +}; +} // End of namespace llvm + +#endif diff --git a/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp b/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp index 4f927f6ba8..567b6e3b18 100644 --- a/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp +++ b/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp @@ -13,12 +13,12 @@ #define DEBUG_TYPE "asm-printer" #include "llvm/CodeGen/AsmPrinter.h" -#include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/Twine.h" #include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/IR/Constants.h" +#include "llvm/IR/DataLayout.h" #include "llvm/IR/InlineAsm.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" @@ -33,6 +33,7 @@ #include "llvm/Support/TargetRegistry.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetSubtargetInfo.h" using namespace llvm; namespace { @@ -77,11 +78,17 @@ void AsmPrinter::EmitInlineAsm(StringRef Str, const MDNode *LocMDNode, if (isNullTerminated) Str = Str.substr(0, Str.size()-1); - // If the output streamer is actually a .s file, just emit the blob textually. + // If the output streamer does not have mature MC support or the integrated + // assembler has been disabled, just emit the blob textually. + // Otherwise parse the asm and emit it via MC support. // This is useful in case the asm parser doesn't handle something but the // system assembler does. - if (OutStreamer.hasRawTextSupport()) { + const MCAsmInfo *MCAI = TM.getMCAsmInfo(); + assert(MCAI && "No MCAsmInfo"); + if (!MCAI->useIntegratedAssembler() && + !OutStreamer.isIntegratedAssemblerRequired()) { OutStreamer.EmitRawText(Str); + emitInlineAsmEnd(TM.getSubtarget<MCSubtargetInfo>(), 0); return; } @@ -110,20 +117,25 @@ void AsmPrinter::EmitInlineAsm(StringRef Str, const MDNode *LocMDNode, // Tell SrcMgr about this buffer, it takes ownership of the buffer. SrcMgr.AddNewSourceBuffer(Buffer, SMLoc()); - OwningPtr<MCAsmParser> Parser(createMCAsmParser(SrcMgr, - OutContext, OutStreamer, - *MAI)); - - // FIXME: It would be nice if we can avoid createing a new instance of - // MCSubtargetInfo here given TargetSubtargetInfo is available. However, - // we have to watch out for asm directives which can change subtarget - // state. e.g. .code 16, .code 32. - OwningPtr<MCSubtargetInfo> - STI(TM.getTarget().createMCSubtargetInfo(TM.getTargetTriple(), - TM.getTargetCPU(), - TM.getTargetFeatureString())); - OwningPtr<MCTargetAsmParser> - TAP(TM.getTarget().createMCAsmParser(*STI, *Parser, *MII)); + std::unique_ptr<MCAsmParser> Parser( + createMCAsmParser(SrcMgr, OutContext, OutStreamer, *MAI)); + + // Initialize the parser with a fresh subtarget info. It is better to use a + // new STI here because the parser may modify it and we do not want those + // modifications to persist after parsing the inlineasm. The modifications + // made by the parser will be seen by the code emitters because it passes + // the current STI down to the EncodeInstruction() method. + std::unique_ptr<MCSubtargetInfo> STI(TM.getTarget().createMCSubtargetInfo( + TM.getTargetTriple(), TM.getTargetCPU(), TM.getTargetFeatureString())); + + // Preserve a copy of the original STI because the parser may modify it. For + // example, when switching between arm and thumb mode. If the target needs to + // emit code to return to the original state it can do so in + // emitInlineAsmEnd(). + MCSubtargetInfo STIOrig = *STI; + + std::unique_ptr<MCTargetAsmParser> TAP( + TM.getTarget().createMCAsmParser(*STI, *Parser, *MII)); if (!TAP) report_fatal_error("Inline asm not supported by this streamer because" " we don't have an asm parser for this target\n"); @@ -133,6 +145,7 @@ void AsmPrinter::EmitInlineAsm(StringRef Str, const MDNode *LocMDNode, // Don't implicitly switch to the text section before the asm. int Res = Parser->Run(/*NoInitialTextSection*/ true, /*NoFinalize*/ true); + emitInlineAsmEnd(STIOrig, STI.get()); if (Res && !HasDiagHandler) report_fatal_error("Error parsing inline asm\n"); } @@ -427,21 +440,14 @@ void AsmPrinter::EmitInlineAsm(const MachineInstr *MI) const { // If this asmstr is empty, just print the #APP/#NOAPP markers. // These are useful to see where empty asm's wound up. if (AsmStr[0] == 0) { - // Don't emit the comments if writing to a .o file. - if (!OutStreamer.hasRawTextSupport()) return; - - OutStreamer.EmitRawText(Twine("\t")+MAI->getCommentString()+ - MAI->getInlineAsmStart()); - OutStreamer.EmitRawText(Twine("\t")+MAI->getCommentString()+ - MAI->getInlineAsmEnd()); + OutStreamer.emitRawComment(MAI->getInlineAsmStart()); + OutStreamer.emitRawComment(MAI->getInlineAsmEnd()); return; } // Emit the #APP start marker. This has to happen even if verbose-asm isn't - // enabled, so we use EmitRawText. - if (OutStreamer.hasRawTextSupport()) - OutStreamer.EmitRawText(Twine("\t")+MAI->getCommentString()+ - MAI->getInlineAsmStart()); + // enabled, so we use emitRawComment. + OutStreamer.emitRawComment(MAI->getInlineAsmStart()); // Get the !srcloc metadata node if we have it, and decode the loc cookie from // it. @@ -476,10 +482,8 @@ void AsmPrinter::EmitInlineAsm(const MachineInstr *MI) const { EmitInlineAsm(OS.str(), LocMD, MI->getInlineAsmDialect()); // Emit the #NOAPP end marker. This has to happen even if verbose-asm isn't - // enabled, so we use EmitRawText. - if (OutStreamer.hasRawTextSupport()) - OutStreamer.EmitRawText(Twine("\t")+MAI->getCommentString()+ - MAI->getInlineAsmEnd()); + // enabled, so we use emitRawComment. + OutStreamer.emitRawComment(MAI->getInlineAsmEnd()); } @@ -491,8 +495,9 @@ void AsmPrinter::EmitInlineAsm(const MachineInstr *MI) const { /// for their own strange codes. void AsmPrinter::PrintSpecial(const MachineInstr *MI, raw_ostream &OS, const char *Code) const { + const DataLayout *DL = TM.getDataLayout(); if (!strcmp(Code, "private")) { - OS << MAI->getPrivateGlobalPrefix(); + OS << DL->getPrivateGlobalPrefix(); } else if (!strcmp(Code, "comment")) { OS << MAI->getCommentString(); } else if (!strcmp(Code, "uid")) { @@ -551,3 +556,5 @@ bool AsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo, return true; } +void AsmPrinter::emitInlineAsmEnd(const MCSubtargetInfo &StartInfo, + const MCSubtargetInfo *EndInfo) const {} diff --git a/lib/CodeGen/AsmPrinter/ByteStreamer.h b/lib/CodeGen/AsmPrinter/ByteStreamer.h new file mode 100644 index 0000000000..6c01d65cc1 --- /dev/null +++ b/lib/CodeGen/AsmPrinter/ByteStreamer.h @@ -0,0 +1,71 @@ +//===-- llvm/CodeGen/ByteStreamer.h - ByteStreamer class --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains a class that can take bytes that would normally be +// streamed via the AsmPrinter. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_BYTESTREAMER_H +#define LLVM_CODEGEN_BYTESTREAMER_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/CodeGen/AsmPrinter.h" +#include "llvm/MC/MCStreamer.h" +#include "DIEHash.h" + +namespace llvm { +class ByteStreamer { + public: + virtual ~ByteStreamer() {} + + // For now we're just handling the calls we need for dwarf emission/hashing. + virtual void EmitInt8(uint8_t Byte, const Twine &Comment = "") = 0; + virtual void EmitSLEB128(uint64_t DWord, const Twine &Comment = "") = 0; + virtual void EmitULEB128(uint64_t DWord, const Twine &Comment = "") = 0; +}; + +class APByteStreamer : public ByteStreamer { +private: + AsmPrinter &AP; + +public: + APByteStreamer(AsmPrinter &Asm) : AP(Asm) {} + void EmitInt8(uint8_t Byte, const Twine &Comment) override { + AP.OutStreamer.AddComment(Comment); + AP.EmitInt8(Byte); + } + void EmitSLEB128(uint64_t DWord, const Twine &Comment) override { + AP.OutStreamer.AddComment(Comment); + AP.EmitSLEB128(DWord); + } + void EmitULEB128(uint64_t DWord, const Twine &Comment) override { + AP.OutStreamer.AddComment(Comment); + AP.EmitULEB128(DWord); + } +}; + +class HashingByteStreamer : public ByteStreamer { + private: + DIEHash &Hash; + public: + HashingByteStreamer(DIEHash &H) : Hash(H) {} + void EmitInt8(uint8_t Byte, const Twine &Comment) override { + Hash.update(Byte); + } + void EmitSLEB128(uint64_t DWord, const Twine &Comment) override { + Hash.addSLEB128(DWord); + } + void EmitULEB128(uint64_t DWord, const Twine &Comment) override { + Hash.addULEB128(DWord); + } +}; +} + +#endif diff --git a/lib/CodeGen/AsmPrinter/CMakeLists.txt b/lib/CodeGen/AsmPrinter/CMakeLists.txt index be484a6fc9..b3eddac191 100644 --- a/lib/CodeGen/AsmPrinter/CMakeLists.txt +++ b/lib/CodeGen/AsmPrinter/CMakeLists.txt @@ -7,12 +7,13 @@ add_llvm_library(LLVMAsmPrinter DIEHash.cpp DwarfAccelTable.cpp DwarfCFIException.cpp - DwarfCompileUnit.cpp DwarfDebug.cpp DwarfException.cpp + DwarfUnit.cpp ErlangGCPrinter.cpp OcamlGCPrinter.cpp Win64Exception.cpp + WinCodeViewLineTables.cpp ) add_dependencies(LLVMAsmPrinter intrinsics_gen) diff --git a/lib/CodeGen/AsmPrinter/DIE.cpp b/lib/CodeGen/AsmPrinter/DIE.cpp index 69444285f4..26e8f2da85 100644 --- a/lib/CodeGen/AsmPrinter/DIE.cpp +++ b/lib/CodeGen/AsmPrinter/DIE.cpp @@ -13,17 +13,18 @@ #include "DIE.h" #include "DwarfDebug.h" +#include "DwarfUnit.h" #include "llvm/ADT/Twine.h" #include "llvm/CodeGen/AsmPrinter.h" #include "llvm/IR/DataLayout.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSymbol.h" -#include "llvm/Support/Allocator.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/Format.h" #include "llvm/Support/FormattedStream.h" +#include "llvm/Support/LEB128.h" #include "llvm/Support/MD5.h" using namespace llvm; @@ -48,7 +49,7 @@ void DIEAbbrevData::Profile(FoldingSetNodeID &ID) const { /// void DIEAbbrev::Profile(FoldingSetNodeID &ID) const { ID.AddInteger(unsigned(Tag)); - ID.AddInteger(ChildrenFlag); + ID.AddInteger(unsigned(Children)); // For each attribute description. for (unsigned i = 0, N = Data.size(); i < N; ++i) @@ -62,7 +63,7 @@ void DIEAbbrev::Emit(AsmPrinter *AP) const { AP->EmitULEB128(Tag, dwarf::TagString(Tag)); // Emit whether it has children DIEs. - AP->EmitULEB128(ChildrenFlag, dwarf::ChildrenString(ChildrenFlag)); + AP->EmitULEB128((unsigned)Children, dwarf::ChildrenString(Children)); // For each attribute description. for (unsigned i = 0, N = Data.size(); i < N; ++i) { @@ -89,7 +90,7 @@ void DIEAbbrev::print(raw_ostream &O) { << " " << dwarf::TagString(Tag) << " " - << dwarf::ChildrenString(ChildrenFlag) + << dwarf::ChildrenString(Children) << '\n'; for (unsigned i = 0, N = Data.size(); i < N; ++i) { @@ -112,27 +113,28 @@ DIE::~DIE() { delete Children[i]; } -/// Climb up the parent chain to get the compile unit DIE to which this DIE +/// Climb up the parent chain to get the unit DIE to which this DIE /// belongs. -const DIE *DIE::getCompileUnit() const { - const DIE *Cu = getCompileUnitOrNull(); +const DIE *DIE::getUnit() const { + const DIE *Cu = getUnitOrNull(); assert(Cu && "We should not have orphaned DIEs."); return Cu; } -/// Climb up the parent chain to get the compile unit DIE this DIE belongs +/// Climb up the parent chain to get the unit DIE this DIE belongs /// to. Return NULL if DIE is not added to an owner yet. -const DIE *DIE::getCompileUnitOrNull() const { +const DIE *DIE::getUnitOrNull() const { const DIE *p = this; while (p) { - if (p->getTag() == dwarf::DW_TAG_compile_unit) + if (p->getTag() == dwarf::DW_TAG_compile_unit || + p->getTag() == dwarf::DW_TAG_type_unit) return p; p = p->getParent(); } return NULL; } -DIEValue *DIE::findAttribute(uint16_t Attribute) { +DIEValue *DIE::findAttribute(dwarf::Attribute Attribute) const { const SmallVectorImpl<DIEValue *> &Values = getValues(); const DIEAbbrev &Abbrevs = getAbbrev(); @@ -159,7 +161,7 @@ void DIE::print(raw_ostream &O, unsigned IndentCount) const { O << Indent << dwarf::TagString(Abbrev.getTag()) << " " - << dwarf::ChildrenString(Abbrev.getChildrenFlag()) << "\n"; + << dwarf::ChildrenString(Abbrev.hasChildren()) << "\n"; } else { O << "Size: " << Size << "\n"; } @@ -215,8 +217,7 @@ void DIEInteger::EmitValue(AsmPrinter *Asm, dwarf::Form Form) const { case dwarf::DW_FORM_flag_present: // Emit something to keep the lines and comments in sync. // FIXME: Is there a better way to do this? - if (Asm->OutStreamer.hasRawTextSupport()) - Asm->OutStreamer.EmitRawText(""); + Asm->OutStreamer.AddBlankLine(); return; case dwarf::DW_FORM_flag: // Fall thru case dwarf::DW_FORM_ref1: // Fall thru @@ -227,6 +228,7 @@ void DIEInteger::EmitValue(AsmPrinter *Asm, dwarf::Form Form) const { case dwarf::DW_FORM_ref4: // Fall thru case dwarf::DW_FORM_data4: Size = 4; break; case dwarf::DW_FORM_ref8: // Fall thru + case dwarf::DW_FORM_ref_sig8: // Fall thru case dwarf::DW_FORM_data8: Size = 8; break; case dwarf::DW_FORM_GNU_str_index: Asm->EmitULEB128(Integer); return; case dwarf::DW_FORM_GNU_addr_index: Asm->EmitULEB128(Integer); return; @@ -253,11 +255,12 @@ unsigned DIEInteger::SizeOf(AsmPrinter *AP, dwarf::Form Form) const { case dwarf::DW_FORM_ref4: // Fall thru case dwarf::DW_FORM_data4: return sizeof(int32_t); case dwarf::DW_FORM_ref8: // Fall thru + case dwarf::DW_FORM_ref_sig8: // Fall thru case dwarf::DW_FORM_data8: return sizeof(int64_t); - case dwarf::DW_FORM_GNU_str_index: return MCAsmInfo::getULEB128Size(Integer); - case dwarf::DW_FORM_GNU_addr_index: return MCAsmInfo::getULEB128Size(Integer); - case dwarf::DW_FORM_udata: return MCAsmInfo::getULEB128Size(Integer); - case dwarf::DW_FORM_sdata: return MCAsmInfo::getSLEB128Size(Integer); + case dwarf::DW_FORM_GNU_str_index: return getULEB128Size(Integer); + case dwarf::DW_FORM_GNU_addr_index: return getULEB128Size(Integer); + case dwarf::DW_FORM_udata: return getULEB128Size(Integer); + case dwarf::DW_FORM_sdata: return getSLEB128Size(Integer); case dwarf::DW_FORM_addr: return AP->getDataLayout().getPointerSize(); default: llvm_unreachable("DIE Value form not supported yet"); } @@ -338,6 +341,7 @@ void DIEDelta::EmitValue(AsmPrinter *AP, dwarf::Form Form) const { /// unsigned DIEDelta::SizeOf(AsmPrinter *AP, dwarf::Form Form) const { if (Form == dwarf::DW_FORM_data4) return 4; + if (Form == dwarf::DW_FORM_sec_offset) return 4; if (Form == dwarf::DW_FORM_strp) return 4; return AP->getDataLayout().getPointerSize(); } @@ -378,7 +382,26 @@ void DIEString::print(raw_ostream &O) const { /// EmitValue - Emit debug information entry offset. /// void DIEEntry::EmitValue(AsmPrinter *AP, dwarf::Form Form) const { - AP->EmitInt32(Entry->getOffset()); + + if (Form == dwarf::DW_FORM_ref_addr) { + const DwarfDebug *DD = AP->getDwarfDebug(); + unsigned Addr = Entry->getOffset(); + assert(!DD->useSplitDwarf() && "TODO: dwo files can't have relocations."); + // For DW_FORM_ref_addr, output the offset from beginning of debug info + // section. Entry->getOffset() returns the offset from start of the + // compile unit. + DwarfCompileUnit *CU = DD->lookupUnit(Entry->getUnit()); + assert(CU && "CUDie should belong to a CU."); + Addr += CU->getDebugInfoOffset(); + if (AP->MAI->doesDwarfUseRelocationsAcrossSections()) + AP->EmitLabelPlusOffset(CU->getSectionSym(), Addr, + DIEEntry::getRefAddrSize(AP)); + else + AP->EmitLabelOffsetDifference(CU->getSectionSym(), Addr, + CU->getSectionSym(), + DIEEntry::getRefAddrSize(AP)); + } else + AP->EmitInt32(Entry->getOffset()); } unsigned DIEEntry::getRefAddrSize(AsmPrinter *AP) { @@ -386,7 +409,9 @@ unsigned DIEEntry::getRefAddrSize(AsmPrinter *AP) { // specified to be four bytes in the DWARF 32-bit format and eight bytes // in the DWARF 64-bit format, while DWARF Version 2 specifies that such // references have the same size as an address on the target system. - if (AP->getDwarfDebug()->getDwarfVersion() == 2) + const DwarfDebug *DD = AP->getDwarfDebug(); + assert(DD && "Expected Dwarf Debug info to be available"); + if (DD->getDwarfVersion() == 2) return AP->getDataLayout().getPointerSize(); return sizeof(int32_t); } @@ -398,12 +423,83 @@ void DIEEntry::print(raw_ostream &O) const { #endif //===----------------------------------------------------------------------===// +// DIETypeSignature Implementation +//===----------------------------------------------------------------------===// +void DIETypeSignature::EmitValue(AsmPrinter *Asm, dwarf::Form Form) const { + assert(Form == dwarf::DW_FORM_ref_sig8); + Asm->OutStreamer.EmitIntValue(Unit.getTypeSignature(), 8); +} + +#ifndef NDEBUG +void DIETypeSignature::print(raw_ostream &O) const { + O << format("Type Unit: 0x%lx", Unit.getTypeSignature()); +} + +void DIETypeSignature::dump() const { print(dbgs()); } +#endif + +//===----------------------------------------------------------------------===// +// DIELoc Implementation +//===----------------------------------------------------------------------===// + +/// ComputeSize - calculate the size of the location expression. +/// +unsigned DIELoc::ComputeSize(AsmPrinter *AP) const { + if (!Size) { + const SmallVectorImpl<DIEAbbrevData> &AbbrevData = Abbrev.getData(); + for (unsigned i = 0, N = Values.size(); i < N; ++i) + Size += Values[i]->SizeOf(AP, AbbrevData[i].getForm()); + } + + return Size; +} + +/// EmitValue - Emit location data. +/// +void DIELoc::EmitValue(AsmPrinter *Asm, dwarf::Form Form) const { + switch (Form) { + default: llvm_unreachable("Improper form for block"); + case dwarf::DW_FORM_block1: Asm->EmitInt8(Size); break; + case dwarf::DW_FORM_block2: Asm->EmitInt16(Size); break; + case dwarf::DW_FORM_block4: Asm->EmitInt32(Size); break; + case dwarf::DW_FORM_block: + case dwarf::DW_FORM_exprloc: + Asm->EmitULEB128(Size); break; + } + + const SmallVectorImpl<DIEAbbrevData> &AbbrevData = Abbrev.getData(); + for (unsigned i = 0, N = Values.size(); i < N; ++i) + Values[i]->EmitValue(Asm, AbbrevData[i].getForm()); +} + +/// SizeOf - Determine size of location data in bytes. +/// +unsigned DIELoc::SizeOf(AsmPrinter *AP, dwarf::Form Form) const { + switch (Form) { + case dwarf::DW_FORM_block1: return Size + sizeof(int8_t); + case dwarf::DW_FORM_block2: return Size + sizeof(int16_t); + case dwarf::DW_FORM_block4: return Size + sizeof(int32_t); + case dwarf::DW_FORM_block: + case dwarf::DW_FORM_exprloc: + return Size + getULEB128Size(Size); + default: llvm_unreachable("Improper form for block"); + } +} + +#ifndef NDEBUG +void DIELoc::print(raw_ostream &O) const { + O << "ExprLoc: "; + DIE::print(O, 5); +} +#endif + +//===----------------------------------------------------------------------===// // DIEBlock Implementation //===----------------------------------------------------------------------===// /// ComputeSize - calculate the size of the block. /// -unsigned DIEBlock::ComputeSize(AsmPrinter *AP) { +unsigned DIEBlock::ComputeSize(AsmPrinter *AP) const { if (!Size) { const SmallVectorImpl<DIEAbbrevData> &AbbrevData = Abbrev.getData(); for (unsigned i = 0, N = Values.size(); i < N; ++i) @@ -436,7 +532,7 @@ unsigned DIEBlock::SizeOf(AsmPrinter *AP, dwarf::Form Form) const { case dwarf::DW_FORM_block1: return Size + sizeof(int8_t); case dwarf::DW_FORM_block2: return Size + sizeof(int16_t); case dwarf::DW_FORM_block4: return Size + sizeof(int32_t); - case dwarf::DW_FORM_block: return Size + MCAsmInfo::getULEB128Size(Size); + case dwarf::DW_FORM_block: return Size + getULEB128Size(Size); default: llvm_unreachable("Improper form for block"); } } @@ -447,3 +543,34 @@ void DIEBlock::print(raw_ostream &O) const { DIE::print(O, 5); } #endif + +//===----------------------------------------------------------------------===// +// DIELocList Implementation +//===----------------------------------------------------------------------===// + +unsigned DIELocList::SizeOf(AsmPrinter *AP, dwarf::Form Form) const { + if (Form == dwarf::DW_FORM_data4) + return 4; + if (Form == dwarf::DW_FORM_sec_offset) + return 4; + return AP->getDataLayout().getPointerSize(); +} + +/// EmitValue - Emit label value. +/// +void DIELocList::EmitValue(AsmPrinter *AP, dwarf::Form Form) const { + DwarfDebug *DD = AP->getDwarfDebug(); + MCSymbol *Label = DD->getDebugLocEntries()[Index].Label; + + if (AP->MAI->doesDwarfUseRelocationsAcrossSections() && !DD->useSplitDwarf()) + AP->EmitSectionOffset(Label, DD->getDebugLocSym()); + else + AP->EmitLabelDifference(Label, DD->getDebugLocSym(), 4); +} + +#ifndef NDEBUG +void DIELocList::print(raw_ostream &O) const { + O << "LocList: " << Index; + +} +#endif diff --git a/lib/CodeGen/AsmPrinter/DIE.h b/lib/CodeGen/AsmPrinter/DIE.h index f4fa326ef6..7fefd4f4cb 100644 --- a/lib/CodeGen/AsmPrinter/DIE.h +++ b/lib/CodeGen/AsmPrinter/DIE.h @@ -16,437 +16,560 @@ #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/SmallVector.h" -#include "llvm/Support/Compiler.h" #include "llvm/Support/Dwarf.h" -#include "llvm/MC/MCExpr.h" #include <vector> namespace llvm { - class AsmPrinter; - class MCSymbol; - class MCSymbolRefExpr; - class raw_ostream; - - //===--------------------------------------------------------------------===// - /// DIEAbbrevData - Dwarf abbreviation data, describes one attribute of a - /// Dwarf abbreviation. - class DIEAbbrevData { - /// Attribute - Dwarf attribute code. - /// - dwarf::Attribute Attribute; - - /// Form - Dwarf form code. - /// - dwarf::Form Form; - public: - DIEAbbrevData(dwarf::Attribute A, dwarf::Form F) : Attribute(A), Form(F) {} - - // Accessors. - dwarf::Attribute getAttribute() const { return Attribute; } - dwarf::Form getForm() const { return Form; } - - /// Profile - Used to gather unique data for the abbreviation folding set. - /// - void Profile(FoldingSetNodeID &ID) const; - }; +class AsmPrinter; +class MCExpr; +class MCSymbol; +class raw_ostream; +class DwarfTypeUnit; + +//===--------------------------------------------------------------------===// +/// DIEAbbrevData - Dwarf abbreviation data, describes one attribute of a +/// Dwarf abbreviation. +class DIEAbbrevData { + /// Attribute - Dwarf attribute code. + /// + dwarf::Attribute Attribute; - //===--------------------------------------------------------------------===// - /// DIEAbbrev - Dwarf abbreviation, describes the organization of a debug - /// information object. - class DIEAbbrev : public FoldingSetNode { - /// Tag - Dwarf tag code. - /// - dwarf::Tag Tag; - - /// ChildrenFlag - Dwarf children flag. - /// - uint16_t ChildrenFlag; - - /// Unique number for node. - /// - unsigned Number; - - /// Data - Raw data bytes for abbreviation. - /// - SmallVector<DIEAbbrevData, 12> Data; - - public: - DIEAbbrev(dwarf::Tag T, uint16_t C) : Tag(T), ChildrenFlag(C), Data() {} - - // Accessors. - dwarf::Tag getTag() const { return Tag; } - unsigned getNumber() const { return Number; } - uint16_t getChildrenFlag() const { return ChildrenFlag; } - const SmallVectorImpl<DIEAbbrevData> &getData() const { return Data; } - void setChildrenFlag(uint16_t CF) { ChildrenFlag = CF; } - void setNumber(unsigned N) { Number = N; } - - /// AddAttribute - Adds another set of attribute information to the - /// abbreviation. - void AddAttribute(dwarf::Attribute Attribute, dwarf::Form Form) { - Data.push_back(DIEAbbrevData(Attribute, Form)); - } + /// Form - Dwarf form code. + /// + dwarf::Form Form; + +public: + DIEAbbrevData(dwarf::Attribute A, dwarf::Form F) : Attribute(A), Form(F) {} + + // Accessors. + dwarf::Attribute getAttribute() const { return Attribute; } + dwarf::Form getForm() const { return Form; } + + /// Profile - Used to gather unique data for the abbreviation folding set. + /// + void Profile(FoldingSetNodeID &ID) const; +}; + +//===--------------------------------------------------------------------===// +/// DIEAbbrev - Dwarf abbreviation, describes the organization of a debug +/// information object. +class DIEAbbrev : public FoldingSetNode { + /// Unique number for node. + /// + unsigned Number; - /// Profile - Used to gather unique data for the abbreviation folding set. - /// - void Profile(FoldingSetNodeID &ID) const; + /// Tag - Dwarf tag code. + /// + dwarf::Tag Tag; - /// Emit - Print the abbreviation using the specified asm printer. - /// - void Emit(AsmPrinter *AP) const; + /// Children - Whether or not this node has children. + /// + // This cheats a bit in all of the uses since the values in the standard + // are 0 and 1 for no children and children respectively. + bool Children; + + /// Data - Raw data bytes for abbreviation. + /// + SmallVector<DIEAbbrevData, 12> Data; + +public: + DIEAbbrev(dwarf::Tag T, bool C) : Tag(T), Children(C), Data() {} + + // Accessors. + dwarf::Tag getTag() const { return Tag; } + unsigned getNumber() const { return Number; } + bool hasChildren() const { return Children; } + const SmallVectorImpl<DIEAbbrevData> &getData() const { return Data; } + void setChildrenFlag(bool hasChild) { Children = hasChild; } + void setNumber(unsigned N) { Number = N; } + + /// AddAttribute - Adds another set of attribute information to the + /// abbreviation. + void AddAttribute(dwarf::Attribute Attribute, dwarf::Form Form) { + Data.push_back(DIEAbbrevData(Attribute, Form)); + } + + /// Profile - Used to gather unique data for the abbreviation folding set. + /// + void Profile(FoldingSetNodeID &ID) const; + + /// Emit - Print the abbreviation using the specified asm printer. + /// + void Emit(AsmPrinter *AP) const; #ifndef NDEBUG - void print(raw_ostream &O); - void dump(); + void print(raw_ostream &O); + void dump(); #endif - }; +}; - //===--------------------------------------------------------------------===// - /// DIE - A structured debug information entry. Has an abbreviation which - /// describes its organization. - class DIEValue; - - class DIE { - protected: - /// Offset - Offset in debug info section. - /// - unsigned Offset; - - /// Size - Size of instance + children. - /// - unsigned Size; - - /// Abbrev - Buffer for constructing abbreviation. - /// - DIEAbbrev Abbrev; - - /// Children DIEs. - /// - std::vector<DIE *> Children; - - DIE *Parent; - - /// Attribute values. - /// - SmallVector<DIEValue*, 12> Values; - - public: - explicit DIE(unsigned Tag) - : Offset(0), Size(0), Abbrev((dwarf::Tag)Tag, dwarf::DW_CHILDREN_no), - Parent(0) {} - virtual ~DIE(); - - // Accessors. - DIEAbbrev &getAbbrev() { return Abbrev; } - const DIEAbbrev &getAbbrev() const { return Abbrev; } - unsigned getAbbrevNumber() const { return Abbrev.getNumber(); } - dwarf::Tag getTag() const { return Abbrev.getTag(); } - unsigned getOffset() const { return Offset; } - unsigned getSize() const { return Size; } - const std::vector<DIE *> &getChildren() const { return Children; } - const SmallVectorImpl<DIEValue*> &getValues() const { return Values; } - DIE *getParent() const { return Parent; } - /// Climb up the parent chain to get the compile unit DIE this DIE belongs - /// to. - const DIE *getCompileUnit() const; - /// Similar to getCompileUnit, returns null when DIE is not added to an - /// owner yet. - const DIE *getCompileUnitOrNull() const; - void setOffset(unsigned O) { Offset = O; } - void setSize(unsigned S) { Size = S; } - - /// addValue - Add a value and attributes to a DIE. - /// - void addValue(dwarf::Attribute Attribute, dwarf::Form Form, - DIEValue *Value) { - Abbrev.AddAttribute(Attribute, Form); - Values.push_back(Value); - } +//===--------------------------------------------------------------------===// +/// DIE - A structured debug information entry. Has an abbreviation which +/// describes its organization. +class DIEValue; - /// addChild - Add a child to the DIE. - /// - void addChild(DIE *Child) { - assert(!Child->getParent()); - Abbrev.setChildrenFlag(dwarf::DW_CHILDREN_yes); - Children.push_back(Child); - Child->Parent = this; - } +class DIE { +protected: + /// Offset - Offset in debug info section. + /// + unsigned Offset; + + /// Size - Size of instance + children. + /// + unsigned Size; + + /// Abbrev - Buffer for constructing abbreviation. + /// + DIEAbbrev Abbrev; + + /// Children DIEs. + /// + std::vector<DIE *> Children; + + DIE *Parent; - /// findAttribute - Find a value in the DIE with the attribute given, returns NULL - /// if no such attribute exists. - DIEValue *findAttribute(uint16_t Attribute); + /// Attribute values. + /// + SmallVector<DIEValue *, 12> Values; + +public: + explicit DIE(unsigned Tag) + : Offset(0), Size(0), Abbrev((dwarf::Tag)Tag, dwarf::DW_CHILDREN_no), + Parent(0) {} + ~DIE(); + + // Accessors. + DIEAbbrev &getAbbrev() { return Abbrev; } + const DIEAbbrev &getAbbrev() const { return Abbrev; } + unsigned getAbbrevNumber() const { return Abbrev.getNumber(); } + dwarf::Tag getTag() const { return Abbrev.getTag(); } + unsigned getOffset() const { return Offset; } + unsigned getSize() const { return Size; } + const std::vector<DIE *> &getChildren() const { return Children; } + const SmallVectorImpl<DIEValue *> &getValues() const { return Values; } + DIE *getParent() const { return Parent; } + /// Climb up the parent chain to get the compile or type unit DIE this DIE + /// belongs to. + const DIE *getUnit() const; + /// Similar to getUnit, returns null when DIE is not added to an + /// owner yet. + const DIE *getUnitOrNull() const; + void setOffset(unsigned O) { Offset = O; } + void setSize(unsigned S) { Size = S; } + + /// addValue - Add a value and attributes to a DIE. + /// + void addValue(dwarf::Attribute Attribute, dwarf::Form Form, DIEValue *Value) { + Abbrev.AddAttribute(Attribute, Form); + Values.push_back(Value); + } + + /// addChild - Add a child to the DIE. + /// + void addChild(DIE *Child) { + assert(!Child->getParent()); + Abbrev.setChildrenFlag(dwarf::DW_CHILDREN_yes); + Children.push_back(Child); + Child->Parent = this; + } + + /// findAttribute - Find a value in the DIE with the attribute given, + /// returns NULL if no such attribute exists. + DIEValue *findAttribute(dwarf::Attribute Attribute) const; #ifndef NDEBUG - void print(raw_ostream &O, unsigned IndentCount = 0) const; - void dump(); + void print(raw_ostream &O, unsigned IndentCount = 0) const; + void dump(); #endif +}; + +//===--------------------------------------------------------------------===// +/// DIEValue - A debug information entry value. Some of these roughly correlate +/// to DWARF attribute classes. +/// +class DIEValue { + virtual void anchor(); + +public: + enum Type { + isInteger, + isString, + isExpr, + isLabel, + isDelta, + isEntry, + isTypeSignature, + isBlock, + isLoc, + isLocList, }; - //===--------------------------------------------------------------------===// - /// DIEValue - A debug information entry value. - /// - class DIEValue { - virtual void anchor(); - public: - enum { - isInteger, - isString, - isExpr, - isLabel, - isDelta, - isEntry, - isBlock - }; - protected: - /// Type - Type of data stored in the value. - /// - unsigned Type; - public: - explicit DIEValue(unsigned T) : Type(T) {} - virtual ~DIEValue() {} - - // Accessors - unsigned getType() const { return Type; } - - /// EmitValue - Emit value via the Dwarf writer. - /// - virtual void EmitValue(AsmPrinter *AP, dwarf::Form Form) const = 0; - - /// SizeOf - Return the size of a value in bytes. - /// - virtual unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const = 0; +protected: + /// Ty - Type of data stored in the value. + /// + Type Ty; + + explicit DIEValue(Type T) : Ty(T) {} + virtual ~DIEValue() {} + +public: + // Accessors + Type getType() const { return Ty; } + + /// EmitValue - Emit value via the Dwarf writer. + /// + virtual void EmitValue(AsmPrinter *AP, dwarf::Form Form) const = 0; + + /// SizeOf - Return the size of a value in bytes. + /// + virtual unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const = 0; #ifndef NDEBUG - virtual void print(raw_ostream &O) const = 0; - void dump() const; + virtual void print(raw_ostream &O) const = 0; + void dump() const; #endif - }; +}; + +//===--------------------------------------------------------------------===// +/// DIEInteger - An integer value DIE. +/// +class DIEInteger : public DIEValue { + uint64_t Integer; - //===--------------------------------------------------------------------===// - /// DIEInteger - An integer value DIE. - /// - class DIEInteger : public DIEValue { - uint64_t Integer; - public: - explicit DIEInteger(uint64_t I) : DIEValue(isInteger), Integer(I) {} - - /// BestForm - Choose the best form for integer. - /// - static dwarf::Form BestForm(bool IsSigned, uint64_t Int) { - if (IsSigned) { - const int64_t SignedInt = Int; - if ((char)Int == SignedInt) return dwarf::DW_FORM_data1; - if ((short)Int == SignedInt) return dwarf::DW_FORM_data2; - if ((int)Int == SignedInt) return dwarf::DW_FORM_data4; - } else { - if ((unsigned char)Int == Int) return dwarf::DW_FORM_data1; - if ((unsigned short)Int == Int) return dwarf::DW_FORM_data2; - if ((unsigned int)Int == Int) return dwarf::DW_FORM_data4; - } - return dwarf::DW_FORM_data8; +public: + explicit DIEInteger(uint64_t I) : DIEValue(isInteger), Integer(I) {} + + /// BestForm - Choose the best form for integer. + /// + static dwarf::Form BestForm(bool IsSigned, uint64_t Int) { + if (IsSigned) { + const int64_t SignedInt = Int; + if ((char)Int == SignedInt) + return dwarf::DW_FORM_data1; + if ((short)Int == SignedInt) + return dwarf::DW_FORM_data2; + if ((int)Int == SignedInt) + return dwarf::DW_FORM_data4; + } else { + if ((unsigned char)Int == Int) + return dwarf::DW_FORM_data1; + if ((unsigned short)Int == Int) + return dwarf::DW_FORM_data2; + if ((unsigned int)Int == Int) + return dwarf::DW_FORM_data4; } + return dwarf::DW_FORM_data8; + } - /// EmitValue - Emit integer of appropriate size. - /// - virtual void EmitValue(AsmPrinter *AP, dwarf::Form Form) const; + /// EmitValue - Emit integer of appropriate size. + /// + void EmitValue(AsmPrinter *AP, dwarf::Form Form) const override; - uint64_t getValue() const { return Integer; } + uint64_t getValue() const { return Integer; } - /// SizeOf - Determine size of integer value in bytes. - /// - virtual unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const; + /// SizeOf - Determine size of integer value in bytes. + /// + unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const override; - // Implement isa/cast/dyncast. - static bool classof(const DIEValue *I) { return I->getType() == isInteger; } + // Implement isa/cast/dyncast. + static bool classof(const DIEValue *I) { return I->getType() == isInteger; } #ifndef NDEBUG - virtual void print(raw_ostream &O) const; + void print(raw_ostream &O) const override; #endif - }; +}; - //===--------------------------------------------------------------------===// - /// DIEExpr - An expression DIE. - // - class DIEExpr : public DIEValue { - const MCExpr *Expr; - public: - explicit DIEExpr(const MCExpr *E) : DIEValue(isExpr), Expr(E) {} +//===--------------------------------------------------------------------===// +/// DIEExpr - An expression DIE. +// +class DIEExpr : public DIEValue { + const MCExpr *Expr; - /// EmitValue - Emit expression value. - /// - virtual void EmitValue(AsmPrinter *AP, dwarf::Form Form) const; +public: + explicit DIEExpr(const MCExpr *E) : DIEValue(isExpr), Expr(E) {} - /// getValue - Get MCExpr. - /// - const MCExpr *getValue() const { return Expr; } + /// EmitValue - Emit expression value. + /// + void EmitValue(AsmPrinter *AP, dwarf::Form Form) const override; - /// SizeOf - Determine size of expression value in bytes. - /// - virtual unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const; + /// getValue - Get MCExpr. + /// + const MCExpr *getValue() const { return Expr; } + + /// SizeOf - Determine size of expression value in bytes. + /// + unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const override; - // Implement isa/cast/dyncast. - static bool classof(const DIEValue *E) { return E->getType() == isExpr; } + // Implement isa/cast/dyncast. + static bool classof(const DIEValue *E) { return E->getType() == isExpr; } #ifndef NDEBUG - virtual void print(raw_ostream &O) const; + void print(raw_ostream &O) const override; #endif - }; +}; + +//===--------------------------------------------------------------------===// +/// DIELabel - A label DIE. +// +class DIELabel : public DIEValue { + const MCSymbol *Label; - //===--------------------------------------------------------------------===// - /// DIELabel - A label DIE. - // - class DIELabel : public DIEValue { - const MCSymbol *Label; - public: - explicit DIELabel(const MCSymbol *L) : DIEValue(isLabel), Label(L) {} +public: + explicit DIELabel(const MCSymbol *L) : DIEValue(isLabel), Label(L) {} - /// EmitValue - Emit label value. - /// - virtual void EmitValue(AsmPrinter *AP, dwarf::Form Form) const; + /// EmitValue - Emit label value. + /// + void EmitValue(AsmPrinter *AP, dwarf::Form Form) const override; - /// getValue - Get MCSymbol. - /// - const MCSymbol *getValue() const { return Label; } + /// getValue - Get MCSymbol. + /// + const MCSymbol *getValue() const { return Label; } - /// SizeOf - Determine size of label value in bytes. - /// - virtual unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const; + /// SizeOf - Determine size of label value in bytes. + /// + unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const override; - // Implement isa/cast/dyncast. - static bool classof(const DIEValue *L) { return L->getType() == isLabel; } + // Implement isa/cast/dyncast. + static bool classof(const DIEValue *L) { return L->getType() == isLabel; } #ifndef NDEBUG - virtual void print(raw_ostream &O) const; + void print(raw_ostream &O) const override; #endif - }; +}; - //===--------------------------------------------------------------------===// - /// DIEDelta - A simple label difference DIE. - /// - class DIEDelta : public DIEValue { - const MCSymbol *LabelHi; - const MCSymbol *LabelLo; - public: - DIEDelta(const MCSymbol *Hi, const MCSymbol *Lo) +//===--------------------------------------------------------------------===// +/// DIEDelta - A simple label difference DIE. +/// +class DIEDelta : public DIEValue { + const MCSymbol *LabelHi; + const MCSymbol *LabelLo; + +public: + DIEDelta(const MCSymbol *Hi, const MCSymbol *Lo) : DIEValue(isDelta), LabelHi(Hi), LabelLo(Lo) {} - /// EmitValue - Emit delta value. - /// - virtual void EmitValue(AsmPrinter *AP, dwarf::Form Form) const; + /// EmitValue - Emit delta value. + /// + void EmitValue(AsmPrinter *AP, dwarf::Form Form) const override; - /// SizeOf - Determine size of delta value in bytes. - /// - virtual unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const; + /// SizeOf - Determine size of delta value in bytes. + /// + unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const override; - // Implement isa/cast/dyncast. - static bool classof(const DIEValue *D) { return D->getType() == isDelta; } + // Implement isa/cast/dyncast. + static bool classof(const DIEValue *D) { return D->getType() == isDelta; } #ifndef NDEBUG - virtual void print(raw_ostream &O) const; + void print(raw_ostream &O) const override; #endif - }; +}; + +//===--------------------------------------------------------------------===// +/// DIEString - A container for string values. +/// +class DIEString : public DIEValue { + const DIEValue *Access; + const StringRef Str; + +public: + DIEString(const DIEValue *Acc, const StringRef S) + : DIEValue(isString), Access(Acc), Str(S) {} - //===--------------------------------------------------------------------===// - /// DIEString - A container for string values. + /// getString - Grab the string out of the object. + StringRef getString() const { return Str; } + + /// EmitValue - Emit delta value. /// - class DIEString : public DIEValue { - const DIEValue *Access; - const StringRef Str; + void EmitValue(AsmPrinter *AP, dwarf::Form Form) const override; - public: - DIEString(const DIEValue *Acc, const StringRef S) - : DIEValue(isString), Access(Acc), Str(S) {} + /// SizeOf - Determine size of delta value in bytes. + /// + unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const override; - /// getString - Grab the string out of the object. - StringRef getString() const { return Str; } + // Implement isa/cast/dyncast. + static bool classof(const DIEValue *D) { return D->getType() == isString; } - /// EmitValue - Emit delta value. - /// - virtual void EmitValue(AsmPrinter *AP, dwarf::Form Form) const; +#ifndef NDEBUG + void print(raw_ostream &O) const override; +#endif +}; - /// SizeOf - Determine size of delta value in bytes. - /// - virtual unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const; +//===--------------------------------------------------------------------===// +/// DIEEntry - A pointer to another debug information entry. An instance of +/// this class can also be used as a proxy for a debug information entry not +/// yet defined (ie. types.) +class DIEEntry : public DIEValue { + DIE *const Entry; - // Implement isa/cast/dyncast. - static bool classof(const DIEValue *D) { return D->getType() == isString; } +public: + explicit DIEEntry(DIE *E) : DIEValue(isEntry), Entry(E) { + assert(E && "Cannot construct a DIEEntry with a null DIE"); + } - #ifndef NDEBUG - virtual void print(raw_ostream &O) const; - #endif - }; + DIE *getEntry() const { return Entry; } - //===--------------------------------------------------------------------===// - /// DIEEntry - A pointer to another debug information entry. An instance of - /// this class can also be used as a proxy for a debug information entry not - /// yet defined (ie. types.) - class DIEEntry : public DIEValue { - DIE *const Entry; - public: - explicit DIEEntry(DIE *E) : DIEValue(isEntry), Entry(E) { - assert(E && "Cannot construct a DIEEntry with a null DIE"); - } + /// EmitValue - Emit debug information entry offset. + /// + void EmitValue(AsmPrinter *AP, dwarf::Form Form) const override; - DIE *getEntry() const { return Entry; } + /// SizeOf - Determine size of debug information entry in bytes. + /// + unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const override { + return Form == dwarf::DW_FORM_ref_addr ? getRefAddrSize(AP) + : sizeof(int32_t); + } - /// EmitValue - Emit debug information entry offset. - /// - virtual void EmitValue(AsmPrinter *AP, dwarf::Form Form) const; + /// Returns size of a ref_addr entry. + static unsigned getRefAddrSize(AsmPrinter *AP); - /// SizeOf - Determine size of debug information entry in bytes. - /// - virtual unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const { - return Form == dwarf::DW_FORM_ref_addr ? getRefAddrSize(AP) - : sizeof(int32_t); - } + // Implement isa/cast/dyncast. + static bool classof(const DIEValue *E) { return E->getType() == isEntry; } + +#ifndef NDEBUG + void print(raw_ostream &O) const override; +#endif +}; + +//===--------------------------------------------------------------------===// +/// \brief A signature reference to a type unit. +class DIETypeSignature : public DIEValue { + const DwarfTypeUnit &Unit; + +public: + explicit DIETypeSignature(const DwarfTypeUnit &Unit) + : DIEValue(isTypeSignature), Unit(Unit) {} + + /// \brief Emit type unit signature. + void EmitValue(AsmPrinter *Asm, dwarf::Form Form) const override; + + /// Returns size of a ref_sig8 entry. + unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const override { + assert(Form == dwarf::DW_FORM_ref_sig8); + return 8; + } + + // \brief Implement isa/cast/dyncast. + static bool classof(const DIEValue *E) { + return E->getType() == isTypeSignature; + } +#ifndef NDEBUG + void print(raw_ostream &O) const override; + void dump() const; +#endif +}; + +//===--------------------------------------------------------------------===// +/// DIELoc - Represents an expression location. +// +class DIELoc : public DIEValue, public DIE { + mutable unsigned Size; // Size in bytes excluding size header. +public: + DIELoc() : DIEValue(isLoc), DIE(0), Size(0) {} - /// Returns size of a ref_addr entry. - static unsigned getRefAddrSize(AsmPrinter *AP); + /// ComputeSize - Calculate the size of the location expression. + /// + unsigned ComputeSize(AsmPrinter *AP) const; - // Implement isa/cast/dyncast. - static bool classof(const DIEValue *E) { return E->getType() == isEntry; } + /// BestForm - Choose the best form for data. + /// + dwarf::Form BestForm(unsigned DwarfVersion) const { + if (DwarfVersion > 3) + return dwarf::DW_FORM_exprloc; + // Pre-DWARF4 location expressions were blocks and not exprloc. + if ((unsigned char)Size == Size) + return dwarf::DW_FORM_block1; + if ((unsigned short)Size == Size) + return dwarf::DW_FORM_block2; + if ((unsigned int)Size == Size) + return dwarf::DW_FORM_block4; + return dwarf::DW_FORM_block; + } + + /// EmitValue - Emit location data. + /// + void EmitValue(AsmPrinter *AP, dwarf::Form Form) const override; + + /// SizeOf - Determine size of location data in bytes. + /// + unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const override; + + // Implement isa/cast/dyncast. + static bool classof(const DIEValue *E) { return E->getType() == isLoc; } #ifndef NDEBUG - virtual void print(raw_ostream &O) const; + void print(raw_ostream &O) const override; #endif - }; +}; - //===--------------------------------------------------------------------===// - /// DIEBlock - A block of values. Primarily used for location expressions. - // - class DIEBlock : public DIEValue, public DIE { - unsigned Size; // Size in bytes excluding size header. - public: - DIEBlock() : DIEValue(isBlock), DIE(0), Size(0) {} - - /// ComputeSize - calculate the size of the block. - /// - unsigned ComputeSize(AsmPrinter *AP); - - /// BestForm - Choose the best form for data. - /// - dwarf::Form BestForm() const { - if ((unsigned char)Size == Size) return dwarf::DW_FORM_block1; - if ((unsigned short)Size == Size) return dwarf::DW_FORM_block2; - if ((unsigned int)Size == Size) return dwarf::DW_FORM_block4; - return dwarf::DW_FORM_block; - } +//===--------------------------------------------------------------------===// +/// DIEBlock - Represents a block of values. +// +class DIEBlock : public DIEValue, public DIE { + mutable unsigned Size; // Size in bytes excluding size header. +public: + DIEBlock() : DIEValue(isBlock), DIE(0), Size(0) {} - /// EmitValue - Emit block data. - /// - virtual void EmitValue(AsmPrinter *AP, dwarf::Form Form) const; + /// ComputeSize - Calculate the size of the location expression. + /// + unsigned ComputeSize(AsmPrinter *AP) const; - /// SizeOf - Determine size of block data in bytes. - /// - virtual unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const; + /// BestForm - Choose the best form for data. + /// + dwarf::Form BestForm() const { + if ((unsigned char)Size == Size) + return dwarf::DW_FORM_block1; + if ((unsigned short)Size == Size) + return dwarf::DW_FORM_block2; + if ((unsigned int)Size == Size) + return dwarf::DW_FORM_block4; + return dwarf::DW_FORM_block; + } + + /// EmitValue - Emit location data. + /// + void EmitValue(AsmPrinter *AP, dwarf::Form Form) const override; + + /// SizeOf - Determine size of location data in bytes. + /// + unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const override; - // Implement isa/cast/dyncast. - static bool classof(const DIEValue *E) { return E->getType() == isBlock; } + // Implement isa/cast/dyncast. + static bool classof(const DIEValue *E) { return E->getType() == isBlock; } #ifndef NDEBUG - virtual void print(raw_ostream &O) const; + void print(raw_ostream &O) const override; #endif - }; +}; + +//===--------------------------------------------------------------------===// +/// DIELocList - Represents a pointer to a location list in the debug_loc +/// section. +// +class DIELocList : public DIEValue { + // Index into the .debug_loc vector. + size_t Index; + +public: + DIELocList(size_t I) : DIEValue(isLocList), Index(I) {} + + /// getValue - Grab the current index out. + size_t getValue() const { return Index; } + + /// EmitValue - Emit location data. + /// + void EmitValue(AsmPrinter *AP, dwarf::Form Form) const override; + + /// SizeOf - Determine size of location data in bytes. + /// + unsigned SizeOf(AsmPrinter *AP, dwarf::Form Form) const override; + + // Implement isa/cast/dyncast. + static bool classof(const DIEValue *E) { return E->getType() == isLocList; } + +#ifndef NDEBUG + void print(raw_ostream &O) const override; +#endif +}; } // end llvm namespace diff --git a/lib/CodeGen/AsmPrinter/DIEHash.cpp b/lib/CodeGen/AsmPrinter/DIEHash.cpp index 95eca90ef0..74beec1c95 100644 --- a/lib/CodeGen/AsmPrinter/DIEHash.cpp +++ b/lib/CodeGen/AsmPrinter/DIEHash.cpp @@ -13,12 +13,13 @@ #define DEBUG_TYPE "dwarfdebug" +#include "ByteStreamer.h" #include "DIEHash.h" - #include "DIE.h" -#include "DwarfCompileUnit.h" +#include "DwarfDebug.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringRef.h" +#include "llvm/CodeGen/AsmPrinter.h" #include "llvm/Support/Debug.h" #include "llvm/Support/Dwarf.h" #include "llvm/Support/Endian.h" @@ -75,7 +76,7 @@ void DIEHash::addSLEB128(int64_t Value) { do { uint8_t Byte = Value & 0x7f; Value >>= 7; - More = !((((Value == 0 ) && ((Byte & 0x40) == 0)) || + More = !((((Value == 0) && ((Byte & 0x40) == 0)) || ((Value == -1) && ((Byte & 0x40) != 0)))); if (More) Byte |= 0x80; // Mark this byte to show that more bytes will follow. @@ -92,10 +93,12 @@ void DIEHash::addParentContext(const DIE &Parent) { // outermost such construct... SmallVector<const DIE *, 1> Parents; const DIE *Cur = &Parent; - while (Cur->getTag() != dwarf::DW_TAG_compile_unit) { + while (Cur->getParent()) { Parents.push_back(Cur); Cur = Cur->getParent(); } + assert(Cur->getTag() == dwarf::DW_TAG_compile_unit || + Cur->getTag() == dwarf::DW_TAG_type_unit); // Reverse iterate over our list to go from the outermost construct to the // innermost. @@ -134,55 +137,55 @@ void DIEHash::collectAttributes(const DIE &Die, DIEAttrs &Attrs) { << dwarf::AttributeString(Abbrevs.getData()[i].getAttribute()) << " added.\n"); switch (Abbrevs.getData()[i].getAttribute()) { - COLLECT_ATTR(DW_AT_name); - COLLECT_ATTR(DW_AT_accessibility); - COLLECT_ATTR(DW_AT_address_class); - COLLECT_ATTR(DW_AT_allocated); - COLLECT_ATTR(DW_AT_artificial); - COLLECT_ATTR(DW_AT_associated); - COLLECT_ATTR(DW_AT_binary_scale); - COLLECT_ATTR(DW_AT_bit_offset); - COLLECT_ATTR(DW_AT_bit_size); - COLLECT_ATTR(DW_AT_bit_stride); - COLLECT_ATTR(DW_AT_byte_size); - COLLECT_ATTR(DW_AT_byte_stride); - COLLECT_ATTR(DW_AT_const_expr); - COLLECT_ATTR(DW_AT_const_value); - COLLECT_ATTR(DW_AT_containing_type); - COLLECT_ATTR(DW_AT_count); - COLLECT_ATTR(DW_AT_data_bit_offset); - COLLECT_ATTR(DW_AT_data_location); - COLLECT_ATTR(DW_AT_data_member_location); - COLLECT_ATTR(DW_AT_decimal_scale); - COLLECT_ATTR(DW_AT_decimal_sign); - COLLECT_ATTR(DW_AT_default_value); - COLLECT_ATTR(DW_AT_digit_count); - COLLECT_ATTR(DW_AT_discr); - COLLECT_ATTR(DW_AT_discr_list); - COLLECT_ATTR(DW_AT_discr_value); - COLLECT_ATTR(DW_AT_encoding); - COLLECT_ATTR(DW_AT_enum_class); - COLLECT_ATTR(DW_AT_endianity); - COLLECT_ATTR(DW_AT_explicit); - COLLECT_ATTR(DW_AT_is_optional); - COLLECT_ATTR(DW_AT_location); - COLLECT_ATTR(DW_AT_lower_bound); - COLLECT_ATTR(DW_AT_mutable); - COLLECT_ATTR(DW_AT_ordering); - COLLECT_ATTR(DW_AT_picture_string); - COLLECT_ATTR(DW_AT_prototyped); - COLLECT_ATTR(DW_AT_small); - COLLECT_ATTR(DW_AT_segment); - COLLECT_ATTR(DW_AT_string_length); - COLLECT_ATTR(DW_AT_threads_scaled); - COLLECT_ATTR(DW_AT_upper_bound); - COLLECT_ATTR(DW_AT_use_location); - COLLECT_ATTR(DW_AT_use_UTF8); - COLLECT_ATTR(DW_AT_variable_parameter); - COLLECT_ATTR(DW_AT_virtuality); - COLLECT_ATTR(DW_AT_visibility); - COLLECT_ATTR(DW_AT_vtable_elem_location); - COLLECT_ATTR(DW_AT_type); + COLLECT_ATTR(DW_AT_name); + COLLECT_ATTR(DW_AT_accessibility); + COLLECT_ATTR(DW_AT_address_class); + COLLECT_ATTR(DW_AT_allocated); + COLLECT_ATTR(DW_AT_artificial); + COLLECT_ATTR(DW_AT_associated); + COLLECT_ATTR(DW_AT_binary_scale); + COLLECT_ATTR(DW_AT_bit_offset); + COLLECT_ATTR(DW_AT_bit_size); + COLLECT_ATTR(DW_AT_bit_stride); + COLLECT_ATTR(DW_AT_byte_size); + COLLECT_ATTR(DW_AT_byte_stride); + COLLECT_ATTR(DW_AT_const_expr); + COLLECT_ATTR(DW_AT_const_value); + COLLECT_ATTR(DW_AT_containing_type); + COLLECT_ATTR(DW_AT_count); + COLLECT_ATTR(DW_AT_data_bit_offset); + COLLECT_ATTR(DW_AT_data_location); + COLLECT_ATTR(DW_AT_data_member_location); + COLLECT_ATTR(DW_AT_decimal_scale); + COLLECT_ATTR(DW_AT_decimal_sign); + COLLECT_ATTR(DW_AT_default_value); + COLLECT_ATTR(DW_AT_digit_count); + COLLECT_ATTR(DW_AT_discr); + COLLECT_ATTR(DW_AT_discr_list); + COLLECT_ATTR(DW_AT_discr_value); + COLLECT_ATTR(DW_AT_encoding); + COLLECT_ATTR(DW_AT_enum_class); + COLLECT_ATTR(DW_AT_endianity); + COLLECT_ATTR(DW_AT_explicit); + COLLECT_ATTR(DW_AT_is_optional); + COLLECT_ATTR(DW_AT_location); + COLLECT_ATTR(DW_AT_lower_bound); + COLLECT_ATTR(DW_AT_mutable); + COLLECT_ATTR(DW_AT_ordering); + COLLECT_ATTR(DW_AT_picture_string); + COLLECT_ATTR(DW_AT_prototyped); + COLLECT_ATTR(DW_AT_small); + COLLECT_ATTR(DW_AT_segment); + COLLECT_ATTR(DW_AT_string_length); + COLLECT_ATTR(DW_AT_threads_scaled); + COLLECT_ATTR(DW_AT_upper_bound); + COLLECT_ATTR(DW_AT_use_location); + COLLECT_ATTR(DW_AT_use_UTF8); + COLLECT_ATTR(DW_AT_variable_parameter); + COLLECT_ATTR(DW_AT_virtuality); + COLLECT_ATTR(DW_AT_visibility); + COLLECT_ATTR(DW_AT_vtable_elem_location); + COLLECT_ATTR(DW_AT_type); default: break; } @@ -269,6 +272,24 @@ void DIEHash::hashDIEEntry(dwarf::Attribute Attribute, dwarf::Tag Tag, computeHash(Entry); } +// Hash all of the values in a block like set of values. This assumes that +// all of the data is going to be added as integers. +void DIEHash::hashBlockData(const SmallVectorImpl<DIEValue *> &Values) { + for (SmallVectorImpl<DIEValue *>::const_iterator I = Values.begin(), + E = Values.end(); + I != E; ++I) + Hash.update((uint64_t)cast<DIEInteger>(*I)->getValue()); +} + +// Hash the contents of a loclistptr class. +void DIEHash::hashLocList(const DIELocList &LocList) { + HashingByteStreamer Streamer(*this); + DwarfDebug &DD = *AP->getDwarfDebug(); + for (const auto &Entry : + DD.getDebugLocEntries()[LocList.getValue()].List) + DD.emitDebugLocEntry(Streamer, Entry); +} + // Hash an individual attribute \param Attr based on the type of attribute and // the form. void DIEHash::hashAttribute(AttrEntry Attr, dwarf::Tag Tag) { @@ -276,43 +297,76 @@ void DIEHash::hashAttribute(AttrEntry Attr, dwarf::Tag Tag) { const DIEAbbrevData *Desc = Attr.Desc; dwarf::Attribute Attribute = Desc->getAttribute(); - // 7.27 Step 3 - // ... An attribute that refers to another type entry T is processed as - // follows: - if (const DIEEntry *EntryAttr = dyn_cast<DIEEntry>(Value)) { - hashDIEEntry(Attribute, Tag, *EntryAttr->getEntry()); - return; + // Other attribute values use the letter 'A' as the marker, and the value + // consists of the form code (encoded as an unsigned LEB128 value) followed by + // the encoding of the value according to the form code. To ensure + // reproducibility of the signature, the set of forms used in the signature + // computation is limited to the following: DW_FORM_sdata, DW_FORM_flag, + // DW_FORM_string, and DW_FORM_block. + + switch (Value->getType()) { + // 7.27 Step 3 + // ... An attribute that refers to another type entry T is processed as + // follows: + case DIEValue::isEntry: + hashDIEEntry(Attribute, Tag, *cast<DIEEntry>(Value)->getEntry()); + break; + case DIEValue::isInteger: { + addULEB128('A'); + addULEB128(Attribute); + switch (Desc->getForm()) { + case dwarf::DW_FORM_data1: + case dwarf::DW_FORM_data2: + case dwarf::DW_FORM_data4: + case dwarf::DW_FORM_data8: + case dwarf::DW_FORM_udata: + case dwarf::DW_FORM_sdata: + addULEB128(dwarf::DW_FORM_sdata); + addSLEB128((int64_t)cast<DIEInteger>(Value)->getValue()); + break; + // DW_FORM_flag_present is just flag with a value of one. We still give it a + // value so just use the value. + case dwarf::DW_FORM_flag_present: + case dwarf::DW_FORM_flag: + addULEB128(dwarf::DW_FORM_flag); + addULEB128((int64_t)cast<DIEInteger>(Value)->getValue()); + break; + default: + llvm_unreachable("Unknown integer form!"); + } + break; } - - // Other attribute values use the letter 'A' as the marker, ... - addULEB128('A'); - - addULEB128(Attribute); - - // ... and the value consists of the form code (encoded as an unsigned LEB128 - // value) followed by the encoding of the value according to the form code. To - // ensure reproducibility of the signature, the set of forms used in the - // signature computation is limited to the following: DW_FORM_sdata, - // DW_FORM_flag, DW_FORM_string, and DW_FORM_block. - switch (Desc->getForm()) { - case dwarf::DW_FORM_string: - llvm_unreachable( - "Add support for DW_FORM_string if we ever start emitting them again"); - case dwarf::DW_FORM_GNU_str_index: - case dwarf::DW_FORM_strp: + case DIEValue::isString: + addULEB128('A'); + addULEB128(Attribute); addULEB128(dwarf::DW_FORM_string); addString(cast<DIEString>(Value)->getString()); break; - case dwarf::DW_FORM_data1: - case dwarf::DW_FORM_data2: - case dwarf::DW_FORM_data4: - case dwarf::DW_FORM_data8: - case dwarf::DW_FORM_udata: - addULEB128(dwarf::DW_FORM_sdata); - addSLEB128((int64_t)cast<DIEInteger>(Value)->getValue()); + case DIEValue::isBlock: + case DIEValue::isLoc: + case DIEValue::isLocList: + addULEB128('A'); + addULEB128(Attribute); + addULEB128(dwarf::DW_FORM_block); + if (isa<DIEBlock>(Value)) { + addULEB128(cast<DIEBlock>(Value)->ComputeSize(AP)); + hashBlockData(cast<DIEBlock>(Value)->getValues()); + } else if (isa<DIELoc>(Value)) { + addULEB128(cast<DIELoc>(Value)->ComputeSize(AP)); + hashBlockData(cast<DIELoc>(Value)->getValues()); + } else { + // We could add the block length, but that would take + // a bit of work and not add a lot of uniqueness + // to the hash in some way we could test. + hashLocList(*cast<DIELocList>(Value)); + } break; - default: - llvm_unreachable("Add support for additional forms"); + // FIXME: It's uncertain whether or not we should handle this at the moment. + case DIEValue::isExpr: + case DIEValue::isLabel: + case DIEValue::isDelta: + case DIEValue::isTypeSignature: + llvm_unreachable("Add support for additional value types."); } } diff --git a/lib/CodeGen/AsmPrinter/DIEHash.h b/lib/CodeGen/AsmPrinter/DIEHash.h index f0c4ef98bb..48f16011e8 100644 --- a/lib/CodeGen/AsmPrinter/DIEHash.h +++ b/lib/CodeGen/AsmPrinter/DIEHash.h @@ -11,17 +11,22 @@ // //===----------------------------------------------------------------------===// +#ifndef CODEGEN_ASMPRINTER_DIEHASH_H__ +#define CODEGEN_ASMPRINTER_DIEHASH_H__ + #include "DIE.h" #include "llvm/ADT/DenseMap.h" #include "llvm/Support/MD5.h" namespace llvm { +class AsmPrinter; class CompileUnit; /// \brief An object containing the capability of hashing and adding hash /// attributes onto a DIE. class DIEHash { + // The entry for a particular attribute. struct AttrEntry { const DIEValue *Val; @@ -84,6 +89,8 @@ class DIEHash { }; public: + DIEHash(AsmPrinter *A = NULL) : AP(A) {} + /// \brief Computes the ODR signature. uint64_t computeDIEODRSignature(const DIE &Die); @@ -105,13 +112,17 @@ private: void computeHash(const DIE &Die); // Routines that add DIEValues to the hash. -private: +public: + /// \brief Adds \param Value to the hash. + void update(uint8_t Value) { Hash.update(Value); } + /// \brief Encodes and adds \param Value to the hash as a ULEB128. void addULEB128(uint64_t Value); /// \brief Encodes and adds \param Value to the hash as a SLEB128. void addSLEB128(int64_t Value); +private: /// \brief Adds \param Str to the hash and includes a NULL byte. void addString(StringRef Str); @@ -122,6 +133,13 @@ private: /// \brief Hashes the attributes in \param Attrs in order. void hashAttributes(const DIEAttrs &Attrs, dwarf::Tag Tag); + /// \brief Hashes the data in a block like DIEValue, e.g. DW_FORM_block or + /// DW_FORM_exprloc. + void hashBlockData(const SmallVectorImpl<DIEValue *> &Values); + + /// \brief Hashes the contents pointed to in the .debug_loc section. + void hashLocList(const DIELocList &LocList); + /// \brief Hashes an individual attribute. void hashAttribute(AttrEntry Attr, dwarf::Tag Tag); @@ -136,12 +154,16 @@ private: StringRef Name); /// \brief Hashes a reference to a previously referenced type DIE. - void hashRepeatedTypeReference(dwarf::Attribute Attribute, unsigned DieNumber); + void hashRepeatedTypeReference(dwarf::Attribute Attribute, + unsigned DieNumber); void hashNestedType(const DIE &Die, StringRef Name); private: MD5 Hash; + AsmPrinter *AP; DenseMap<const DIE *, unsigned> Numbering; }; } + +#endif diff --git a/lib/CodeGen/AsmPrinter/DebugLocEntry.h b/lib/CodeGen/AsmPrinter/DebugLocEntry.h new file mode 100644 index 0000000000..470453fbe2 --- /dev/null +++ b/lib/CodeGen/AsmPrinter/DebugLocEntry.h @@ -0,0 +1,123 @@ +//===-- llvm/CodeGen/DebugLocEntry.h - Entry in debug_loc list -*- C++ -*--===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef CODEGEN_ASMPRINTER_DEBUGLOCENTRY_H__ +#define CODEGEN_ASMPRINTER_DEBUGLOCENTRY_H__ +#include "llvm/IR/Constants.h" +#include "llvm/MC/MachineLocation.h" +#include "llvm/MC/MCSymbol.h" + +namespace llvm { +class DwarfCompileUnit; +class MDNode; +/// \brief This struct describes location entries emitted in the .debug_loc +/// section. +class DebugLocEntry { + // Begin and end symbols for the address range that this location is valid. + const MCSymbol *Begin; + const MCSymbol *End; + + // Type of entry that this represents. + enum EntryType { E_Location, E_Integer, E_ConstantFP, E_ConstantInt }; + enum EntryType EntryKind; + + union { + int64_t Int; + const ConstantFP *CFP; + const ConstantInt *CIP; + } Constants; + + // The location in the machine frame. + MachineLocation Loc; + + // The variable to which this location entry corresponds. + const MDNode *Variable; + + // The compile unit to which this location entry is referenced by. + const DwarfCompileUnit *Unit; + + bool hasSameValueOrLocation(const DebugLocEntry &Next) { + if (EntryKind != Next.EntryKind) + return false; + + bool EqualValues; + switch (EntryKind) { + case E_Location: + EqualValues = Loc == Next.Loc; + break; + case E_Integer: + EqualValues = Constants.Int == Next.Constants.Int; + break; + case E_ConstantFP: + EqualValues = Constants.CFP == Next.Constants.CFP; + break; + case E_ConstantInt: + EqualValues = Constants.CIP == Next.Constants.CIP; + break; + } + + return EqualValues; + } + +public: + DebugLocEntry() : Begin(0), End(0), Variable(0), Unit(0) { + Constants.Int = 0; + } + DebugLocEntry(const MCSymbol *B, const MCSymbol *E, MachineLocation &L, + const MDNode *V, const DwarfCompileUnit *U) + : Begin(B), End(E), Loc(L), Variable(V), Unit(U) { + Constants.Int = 0; + EntryKind = E_Location; + } + DebugLocEntry(const MCSymbol *B, const MCSymbol *E, int64_t i, + const DwarfCompileUnit *U) + : Begin(B), End(E), Variable(0), Unit(U) { + Constants.Int = i; + EntryKind = E_Integer; + } + DebugLocEntry(const MCSymbol *B, const MCSymbol *E, const ConstantFP *FPtr, + const DwarfCompileUnit *U) + : Begin(B), End(E), Variable(0), Unit(U) { + Constants.CFP = FPtr; + EntryKind = E_ConstantFP; + } + DebugLocEntry(const MCSymbol *B, const MCSymbol *E, const ConstantInt *IPtr, + const DwarfCompileUnit *U) + : Begin(B), End(E), Variable(0), Unit(U) { + Constants.CIP = IPtr; + EntryKind = E_ConstantInt; + } + + /// \brief Attempt to merge this DebugLocEntry with Next and return + /// true if the merge was successful. Entries can be merged if they + /// share the same Loc/Constant and if Next immediately follows this + /// Entry. + bool Merge(const DebugLocEntry &Next) { + if (End == Next.Begin && hasSameValueOrLocation(Next)) { + End = Next.End; + return true; + } + return false; + } + bool isLocation() const { return EntryKind == E_Location; } + bool isInt() const { return EntryKind == E_Integer; } + bool isConstantFP() const { return EntryKind == E_ConstantFP; } + bool isConstantInt() const { return EntryKind == E_ConstantInt; } + int64_t getInt() const { return Constants.Int; } + const ConstantFP *getConstantFP() const { return Constants.CFP; } + const ConstantInt *getConstantInt() const { return Constants.CIP; } + const MDNode *getVariable() const { return Variable; } + const MCSymbol *getBeginSym() const { return Begin; } + const MCSymbol *getEndSym() const { return End; } + const DwarfCompileUnit *getCU() const { return Unit; } + MachineLocation getLoc() const { return Loc; } +}; + +} +#endif diff --git a/lib/CodeGen/AsmPrinter/DebugLocList.h b/lib/CodeGen/AsmPrinter/DebugLocList.h new file mode 100644 index 0000000000..7a51c7bd5b --- /dev/null +++ b/lib/CodeGen/AsmPrinter/DebugLocList.h @@ -0,0 +1,23 @@ +//===--- lib/CodeGen/DebugLocList.h - DWARF debug_loc list ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef CODEGEN_ASMPRINTER_DEBUGLOCLIST_H__ +#define CODEGEN_ASMPRINTER_DEBUGLOCLIST_H__ + +#include "llvm/MC/MCSymbol.h" +#include "llvm/ADT/SmallVector.h" +#include "DebugLocEntry.h" + +namespace llvm { +struct DebugLocList { + MCSymbol *Label; + SmallVector<DebugLocEntry, 4> List; +}; +} +#endif diff --git a/lib/CodeGen/AsmPrinter/DwarfAccelTable.cpp b/lib/CodeGen/AsmPrinter/DwarfAccelTable.cpp index 689aeda86a..bcbb6c8455 100644 --- a/lib/CodeGen/AsmPrinter/DwarfAccelTable.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfAccelTable.cpp @@ -31,7 +31,7 @@ DwarfAccelTable::DwarfAccelTable(ArrayRef<DwarfAccelTable::Atom> atomList) DwarfAccelTable::~DwarfAccelTable() {} -void DwarfAccelTable::AddName(StringRef Name, DIE *die, char Flags) { +void DwarfAccelTable::AddName(StringRef Name, const DIE *die, char Flags) { assert(Data.empty() && "Already finalized!"); // If the string is in the list already then add this die to the list // otherwise add a new one. @@ -172,7 +172,7 @@ void DwarfAccelTable::EmitOffsets(AsmPrinter *Asm, MCSymbol *SecBegin) { // Walk through the buckets and emit the full data for each element in // the bucket. For the string case emit the dies and the various offsets. // Terminate each HashData bucket with 0. -void DwarfAccelTable::EmitData(AsmPrinter *Asm, DwarfUnits *D) { +void DwarfAccelTable::EmitData(AsmPrinter *Asm, DwarfFile *D) { uint64_t PrevHash = UINT64_MAX; for (size_t i = 0, e = Buckets.size(); i < e; ++i) { for (HashList::const_iterator HI = Buckets[i].begin(), @@ -207,7 +207,7 @@ void DwarfAccelTable::EmitData(AsmPrinter *Asm, DwarfUnits *D) { } // Emit the entire data structure to the output file. -void DwarfAccelTable::Emit(AsmPrinter *Asm, MCSymbol *SecBegin, DwarfUnits *D) { +void DwarfAccelTable::Emit(AsmPrinter *Asm, MCSymbol *SecBegin, DwarfFile *D) { // Emit the header. EmitHeader(Asm); diff --git a/lib/CodeGen/AsmPrinter/DwarfAccelTable.h b/lib/CodeGen/AsmPrinter/DwarfAccelTable.h index 7627313d28..4a144978b0 100644 --- a/lib/CodeGen/AsmPrinter/DwarfAccelTable.h +++ b/lib/CodeGen/AsmPrinter/DwarfAccelTable.h @@ -24,7 +24,6 @@ #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/Format.h" #include "llvm/Support/FormattedStream.h" -#include <map> #include <vector> // The dwarf accelerator tables are an indirect hash table optimized @@ -62,8 +61,7 @@ namespace llvm { class AsmPrinter; -class DIE; -class DwarfUnits; +class DwarfFile; class DwarfAccelTable { @@ -165,10 +163,10 @@ private: // HashData[hash_data_count] public: struct HashDataContents { - DIE *Die; // Offsets + const DIE *Die; // Offsets char Flags; // Specific flags to output - HashDataContents(DIE *D, char Flags) : Die(D), Flags(Flags) {} + HashDataContents(const DIE *D, char Flags) : Die(D), Flags(Flags) {} #ifndef NDEBUG void print(raw_ostream &O) const { O << " Offset: " << Die->getOffset() << "\n"; @@ -216,7 +214,7 @@ private: void EmitBuckets(AsmPrinter *); void EmitHashes(AsmPrinter *); void EmitOffsets(AsmPrinter *, MCSymbol *); - void EmitData(AsmPrinter *, DwarfUnits *D); + void EmitData(AsmPrinter *, DwarfFile *D); // Allocator for HashData and HashDataContents. BumpPtrAllocator Allocator; @@ -241,9 +239,9 @@ private: public: DwarfAccelTable(ArrayRef<DwarfAccelTable::Atom>); ~DwarfAccelTable(); - void AddName(StringRef, DIE *, char = 0); + void AddName(StringRef, const DIE *, char = 0); void FinalizeTable(AsmPrinter *, StringRef); - void Emit(AsmPrinter *, MCSymbol *, DwarfUnits *); + void Emit(AsmPrinter *, MCSymbol *, DwarfFile *); #ifndef NDEBUG void print(raw_ostream &O); void dump() { print(dbgs()); } diff --git a/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp b/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp index 8918f3de0a..30312ac2e2 100644 --- a/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp @@ -20,6 +20,7 @@ #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/IR/DataLayout.h" +#include "llvm/IR/Mangler.h" #include "llvm/IR/Module.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCContext.h" @@ -31,7 +32,6 @@ #include "llvm/Support/Dwarf.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/FormattedStream.h" -#include "llvm/Target/Mangler.h" #include "llvm/Target/TargetFrameLowering.h" #include "llvm/Target/TargetLoweringObjectFile.h" #include "llvm/Target/TargetMachine.h" @@ -46,9 +46,9 @@ DwarfCFIException::DwarfCFIException(AsmPrinter *A) DwarfCFIException::~DwarfCFIException() {} -/// EndModule - Emit all exception information that should come after the +/// endModule - Emit all exception information that should come after the /// content. -void DwarfCFIException::EndModule() { +void DwarfCFIException::endModule() { if (moveTypeModule == AsmPrinter::CFI_M_Debug) Asm->OutStreamer.EmitCFISections(false, true); @@ -82,9 +82,9 @@ void DwarfCFIException::EndModule() { } } -/// BeginFunction - Gather pre-function exception information. Assumes it's +/// beginFunction - Gather pre-function exception information. Assumes it's /// being emitted immediately after the function entry point. -void DwarfCFIException::BeginFunction(const MachineFunction *MF) { +void DwarfCFIException::beginFunction(const MachineFunction *MF) { shouldEmitMoves = shouldEmitPersonality = shouldEmitLSDA = false; // If any landing pads survive, we need an EH table. @@ -113,13 +113,14 @@ void DwarfCFIException::BeginFunction(const MachineFunction *MF) { if (!shouldEmitPersonality && !shouldEmitMoves) return; - Asm->OutStreamer.EmitCFIStartProc(); + Asm->OutStreamer.EmitCFIStartProc(/*IsSimple=*/false); // Indicate personality routine, if any. if (!shouldEmitPersonality) return; - const MCSymbol *Sym = TLOF.getCFIPersonalitySymbol(Per, Asm->Mang, MMI); + const MCSymbol *Sym = + TLOF.getCFIPersonalitySymbol(Per, *Asm->Mang, Asm->TM, MMI); Asm->OutStreamer.EmitCFIPersonality(Sym, PerEncoding); Asm->OutStreamer.EmitDebugLabel @@ -135,9 +136,9 @@ void DwarfCFIException::BeginFunction(const MachineFunction *MF) { LSDAEncoding); } -/// EndFunction - Gather and emit post-function exception information. +/// endFunction - Gather and emit post-function exception information. /// -void DwarfCFIException::EndFunction() { +void DwarfCFIException::endFunction(const MachineFunction *) { if (!shouldEmitPersonality && !shouldEmitMoves) return; diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp index 24e2c05398..11345eb288 100644 --- a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -12,23 +12,25 @@ //===----------------------------------------------------------------------===// #define DEBUG_TYPE "dwarfdebug" +#include "ByteStreamer.h" #include "DwarfDebug.h" #include "DIE.h" #include "DIEHash.h" #include "DwarfAccelTable.h" -#include "DwarfCompileUnit.h" +#include "DwarfUnit.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/Statistic.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/Triple.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineModuleInfo.h" -#include "llvm/DIBuilder.h" -#include "llvm/DebugInfo.h" #include "llvm/IR/Constants.h" +#include "llvm/IR/DIBuilder.h" #include "llvm/IR/DataLayout.h" +#include "llvm/IR/DebugInfo.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/Module.h" +#include "llvm/IR/ValueHandle.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCSection.h" #include "llvm/MC/MCStreamer.h" @@ -38,10 +40,10 @@ #include "llvm/Support/Dwarf.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/FormattedStream.h" +#include "llvm/Support/LEB128.h" #include "llvm/Support/MD5.h" #include "llvm/Support/Path.h" #include "llvm/Support/Timer.h" -#include "llvm/Support/ValueHandle.h" #include "llvm/Target/TargetFrameLowering.h" #include "llvm/Target/TargetLoweringObjectFile.h" #include "llvm/Target/TargetMachine.h" @@ -59,26 +61,17 @@ static cl::opt<bool> UnknownLocations( cl::init(false)); static cl::opt<bool> -GenerateODRHash("generate-odr-hash", cl::Hidden, - cl::desc("Add an ODR hash to external type DIEs."), - cl::init(false)); - -static cl::opt<bool> -GenerateCUHash("generate-cu-hash", cl::Hidden, - cl::desc("Add the CU hash as the dwo_id."), - cl::init(false)); - -static cl::opt<bool> GenerateGnuPubSections("generate-gnu-dwarf-pub-sections", cl::Hidden, cl::desc("Generate GNU-style pubnames and pubtypes"), cl::init(false)); +static cl::opt<bool> GenerateARangeSection("generate-arange-section", + cl::Hidden, + cl::desc("Generate dwarf aranges"), + cl::init(false)); + namespace { -enum DefaultOnOff { - Default, - Enable, - Disable -}; +enum DefaultOnOff { Default, Enable, Disable }; } static cl::opt<DefaultOnOff> @@ -91,7 +84,7 @@ DwarfAccelTables("dwarf-accel-tables", cl::Hidden, static cl::opt<DefaultOnOff> SplitDwarf("split-dwarf", cl::Hidden, - cl::desc("Output prototype dwarf split debug info."), + cl::desc("Output DWARF5 split debug info."), cl::values(clEnumVal(Default, "Default for platform"), clEnumVal(Enable, "Enabled"), clEnumVal(Disable, "Disabled"), clEnumValEnd), @@ -105,29 +98,34 @@ DwarfPubSections("generate-dwarf-pub-sections", cl::Hidden, clEnumVal(Disable, "Disabled"), clEnumValEnd), cl::init(Default)); +static cl::opt<unsigned> +DwarfVersionNumber("dwarf-version", cl::Hidden, + cl::desc("Generate DWARF for dwarf version."), cl::init(0)); + static const char *const DWARFGroupName = "DWARF Emission"; static const char *const DbgTimerName = "DWARF Debug Writer"; //===----------------------------------------------------------------------===// -// Configuration values for initial hash set sizes (log2). -// -static const unsigned InitAbbreviationsSetSize = 9; // log2(512) - namespace llvm { /// resolve - Look in the DwarfDebug map for the MDNode that /// corresponds to the reference. -template <typename T> -T DbgVariable::resolve(DIRef<T> Ref) const { +template <typename T> T DbgVariable::resolve(DIRef<T> Ref) const { return DD->resolve(Ref); } +bool DbgVariable::isBlockByrefVariable() const { + assert(Var.isVariable() && "Invalid complex DbgVariable!"); + return Var.isBlockByrefVariable(DD->getTypeIdentifierMap()); +} + + DIType DbgVariable::getType() const { - DIType Ty = Var.getType(); + DIType Ty = Var.getType().resolve(DD->getTypeIdentifierMap()); // FIXME: isBlockByrefVariable should be reformulated in terms of complex // addresses instead. - if (Var.isBlockByrefVariable()) { + if (Var.isBlockByrefVariable(DD->getTypeIdentifierMap())) { /* Byref variables, in Blocks, are declared by the programmer as "SomeType VarName;", but the compiler creates a __Block_byref_x_VarName struct, and gives the variable VarName @@ -179,22 +177,18 @@ static unsigned getDwarfVersionFromModule(const Module *M) { } DwarfDebug::DwarfDebug(AsmPrinter *A, Module *M) - : Asm(A), MMI(Asm->MMI), FirstCU(0), - AbbreviationsSet(InitAbbreviationsSetSize), - SourceIdMap(DIEValueAllocator), - PrevLabel(NULL), GlobalCUIndexCount(0), - InfoHolder(A, &AbbreviationsSet, Abbreviations, "info_string", - DIEValueAllocator), - SkeletonAbbrevSet(InitAbbreviationsSetSize), - SkeletonHolder(A, &SkeletonAbbrevSet, SkeletonAbbrevs, "skel_string", - DIEValueAllocator) { - - DwarfInfoSectionSym = DwarfAbbrevSectionSym = 0; - DwarfStrSectionSym = TextSectionSym = 0; + : Asm(A), MMI(Asm->MMI), FirstCU(0), PrevLabel(NULL), GlobalRangeCount(0), + InfoHolder(A, "info_string", DIEValueAllocator), + UsedNonDefaultText(false), + SkeletonHolder(A, "skel_string", DIEValueAllocator) { + + DwarfInfoSectionSym = DwarfAbbrevSectionSym = DwarfStrSectionSym = 0; DwarfDebugRangeSectionSym = DwarfDebugLocSectionSym = DwarfLineSectionSym = 0; DwarfAddrSectionSym = 0; DwarfAbbrevDWOSectionSym = DwarfStrDWOSectionSym = 0; FunctionBeginSym = FunctionEndSym = 0; + CurFn = 0; + CurMI = 0; // Turn on accelerator tables for Darwin by default, pubnames by // default for non-Darwin, and handle split dwarf. @@ -215,7 +209,9 @@ DwarfDebug::DwarfDebug(AsmPrinter *A, Module *M) else HasDwarfPubSections = DwarfPubSections == Enable; - DwarfVersion = getDwarfVersionFromModule(MMI->getModule()); + DwarfVersion = DwarfVersionNumber + ? DwarfVersionNumber + : getDwarfVersionFromModule(MMI->getModule()); { NamedRegionTimer T(DbgTimerName, DWARFGroupName, TimePassesIsEnabled); @@ -228,53 +224,57 @@ DwarfDebug::DwarfDebug(AsmPrinter *A, Module *M) static MCSymbol *emitSectionSym(AsmPrinter *Asm, const MCSection *Section, const char *SymbolStem = 0) { Asm->OutStreamer.SwitchSection(Section); - if (!SymbolStem) return 0; + if (!SymbolStem) + return 0; MCSymbol *TmpSym = Asm->GetTempSymbol(SymbolStem); Asm->OutStreamer.EmitLabel(TmpSym); return TmpSym; } -MCSymbol *DwarfUnits::getStringPoolSym() { +DwarfFile::~DwarfFile() { + for (DwarfUnit *DU : CUs) + delete DU; +} + +MCSymbol *DwarfFile::getStringPoolSym() { return Asm->GetTempSymbol(StringPref); } -MCSymbol *DwarfUnits::getStringPoolEntry(StringRef Str) { - std::pair<MCSymbol*, unsigned> &Entry = - StringPool.GetOrCreateValue(Str).getValue(); - if (Entry.first) return Entry.first; +MCSymbol *DwarfFile::getStringPoolEntry(StringRef Str) { + std::pair<MCSymbol *, unsigned> &Entry = + StringPool.GetOrCreateValue(Str).getValue(); + if (Entry.first) + return Entry.first; Entry.second = NextStringPoolNumber++; return Entry.first = Asm->GetTempSymbol(StringPref, Entry.second); } -unsigned DwarfUnits::getStringPoolIndex(StringRef Str) { - std::pair<MCSymbol*, unsigned> &Entry = - StringPool.GetOrCreateValue(Str).getValue(); - if (Entry.first) return Entry.second; +unsigned DwarfFile::getStringPoolIndex(StringRef Str) { + std::pair<MCSymbol *, unsigned> &Entry = + StringPool.GetOrCreateValue(Str).getValue(); + if (Entry.first) + return Entry.second; Entry.second = NextStringPoolNumber++; Entry.first = Asm->GetTempSymbol(StringPref, Entry.second); return Entry.second; } -unsigned DwarfUnits::getAddrPoolIndex(const MCSymbol *Sym) { - return getAddrPoolIndex(MCSymbolRefExpr::Create(Sym, Asm->OutContext)); -} - -unsigned DwarfUnits::getAddrPoolIndex(const MCExpr *Sym) { - std::pair<DenseMap<const MCExpr *, unsigned>::iterator, bool> P = - AddressPool.insert(std::make_pair(Sym, NextAddrPoolNumber)); +unsigned DwarfFile::getAddrPoolIndex(const MCSymbol *Sym, bool TLS) { + std::pair<AddrPool::iterator, bool> P = AddressPool.insert( + std::make_pair(Sym, AddressPoolEntry(NextAddrPoolNumber, TLS))); if (P.second) ++NextAddrPoolNumber; - return P.first->second; + return P.first->second.Number; } // Define a unique number for the abbreviation. // -void DwarfUnits::assignAbbrevNumber(DIEAbbrev &Abbrev) { +void DwarfFile::assignAbbrevNumber(DIEAbbrev &Abbrev) { // Check the set for priors. - DIEAbbrev *InSet = AbbreviationsSet->GetOrInsertNode(&Abbrev); + DIEAbbrev *InSet = AbbreviationsSet.GetOrInsertNode(&Abbrev); // If it's newly added. if (InSet == &Abbrev) { @@ -294,7 +294,8 @@ static bool isObjCClass(StringRef Name) { } static bool hasObjCCategory(StringRef Name) { - if (!isObjCClass(Name)) return false; + if (!isObjCClass(Name)) + return false; return Name.find(") ") != StringRef::npos; } @@ -318,35 +319,35 @@ static StringRef getObjCMethodName(StringRef In) { // Helper for sorting sections into a stable output order. static bool SectionSort(const MCSection *A, const MCSection *B) { - std::string LA = (A ? A->getLabelBeginName() : ""); - std::string LB = (B ? B->getLabelBeginName() : ""); - return LA < LB; + std::string LA = (A ? A->getLabelBeginName() : ""); + std::string LB = (B ? B->getLabelBeginName() : ""); + return LA < LB; } // Add the various names to the Dwarf accelerator table names. // TODO: Determine whether or not we should add names for programs // that do not have a DW_AT_name or DW_AT_linkage_name field - this // is only slightly different than the lookup of non-standard ObjC names. -static void addSubprogramNames(CompileUnit *TheCU, DISubprogram SP, - DIE* Die) { - if (!SP.isDefinition()) return; - TheCU->addAccelName(SP.getName(), Die); +static void addSubprogramNames(DwarfUnit *TheU, DISubprogram SP, DIE *Die) { + if (!SP.isDefinition()) + return; + TheU->addAccelName(SP.getName(), Die); // If the linkage name is different than the name, go ahead and output // that as well into the name table. if (SP.getLinkageName() != "" && SP.getName() != SP.getLinkageName()) - TheCU->addAccelName(SP.getLinkageName(), Die); + TheU->addAccelName(SP.getLinkageName(), Die); // If this is an Objective-C selector name add it to the ObjC accelerator // too. if (isObjCClass(SP.getName())) { StringRef Class, Category; getObjCClassCategory(SP.getName(), Class, Category); - TheCU->addAccelObjC(Class, Die); + TheU->addAccelObjC(Class, Die); if (Category != "") - TheCU->addAccelObjC(Category, Die); + TheU->addAccelObjC(Category, Die); // Also add the base method name to the name table. - TheCU->addAccelName(getObjCMethodName(SP.getName()), Die); + TheU->addAccelName(getObjCMethodName(SP.getName()), Die); } } @@ -366,7 +367,8 @@ bool DwarfDebug::isSubprogramContext(const MDNode *Context) { // Find DIE for the given subprogram and attach appropriate DW_AT_low_pc // and DW_AT_high_pc attributes. If there are global variables in this // scope then create and insert DIEs for these variables. -DIE *DwarfDebug::updateSubprogramScopeDIE(CompileUnit *SPCU, DISubprogram SP) { +DIE *DwarfDebug::updateSubprogramScopeDIE(DwarfCompileUnit *SPCU, + DISubprogram SP) { DIE *SPDie = SPCU->getDIE(SP); assert(SPDie && "Unable to find subprogram DIE!"); @@ -376,7 +378,8 @@ DIE *DwarfDebug::updateSubprogramScopeDIE(CompileUnit *SPCU, DISubprogram SP) { // concrete DIE twice. if (DIE *AbsSPDIE = AbstractSPDies.lookup(SP)) { // Pick up abstract subprogram DIE. - SPDie = SPCU->createAndAddDIE(dwarf::DW_TAG_subprogram, *SPCU->getCUDie()); + SPDie = + SPCU->createAndAddDIE(dwarf::DW_TAG_subprogram, *SPCU->getUnitDie()); SPCU->addDIEEntry(SPDie, dwarf::DW_AT_abstract_origin, AbsSPDIE); } else { DISubprogram SPDecl = SP.getFunctionDeclaration(); @@ -388,8 +391,7 @@ DIE *DwarfDebug::updateSubprogramScopeDIE(CompileUnit *SPCU, DISubprogram SP) { // specification DIE for a function defined inside a function. DIScope SPContext = resolve(SP.getContext()); if (SP.isDefinition() && !SPContext.isCompileUnit() && - !SPContext.isFile() && - !isSubprogramContext(SPContext)) { + !SPContext.isFile() && !isSubprogramContext(SPContext)) { SPCU->addFlag(SPDie, dwarf::DW_AT_declaration); // Add arguments. @@ -397,30 +399,17 @@ DIE *DwarfDebug::updateSubprogramScopeDIE(CompileUnit *SPCU, DISubprogram SP) { DIArray Args = SPTy.getTypeArray(); uint16_t SPTag = SPTy.getTag(); if (SPTag == dwarf::DW_TAG_subroutine_type) - for (unsigned i = 1, N = Args.getNumElements(); i < N; ++i) { - DIE *Arg = - SPCU->createAndAddDIE(dwarf::DW_TAG_formal_parameter, *SPDie); - DIType ATy(Args.getElement(i)); - SPCU->addType(Arg, ATy); - if (ATy.isArtificial()) - SPCU->addFlag(Arg, dwarf::DW_AT_artificial); - if (ATy.isObjectPointer()) - SPCU->addDIEEntry(SPDie, dwarf::DW_AT_object_pointer, Arg); - } + SPCU->constructSubprogramArguments(*SPDie, Args); DIE *SPDeclDie = SPDie; - SPDie = - SPCU->createAndAddDIE(dwarf::DW_TAG_subprogram, *SPCU->getCUDie()); + SPDie = SPCU->createAndAddDIE(dwarf::DW_TAG_subprogram, + *SPCU->getUnitDie()); SPCU->addDIEEntry(SPDie, dwarf::DW_AT_specification, SPDeclDie); } } } - SPCU->addLabelAddress(SPDie, dwarf::DW_AT_low_pc, - Asm->GetTempSymbol("func_begin", - Asm->getFunctionNumber())); - SPCU->addLabelAddress(SPDie, dwarf::DW_AT_high_pc, - Asm->GetTempSymbol("func_end", - Asm->getFunctionNumber())); + attachLowHighPC(SPCU, SPDie, FunctionBeginSym, FunctionEndSym); + const TargetRegisterInfo *RI = Asm->TM.getRegisterInfo(); MachineLocation Location(RI->getFrameRegister(*Asm->MF)); SPCU->addAddress(SPDie, dwarf::DW_AT_frame_base, Location); @@ -453,9 +442,43 @@ bool DwarfDebug::isLexicalScopeDIENull(LexicalScope *Scope) { return !End; } +static void addSectionLabel(AsmPrinter *Asm, DwarfUnit *U, DIE *D, + dwarf::Attribute A, const MCSymbol *L, + const MCSymbol *Sec) { + if (Asm->MAI->doesDwarfUseRelocationsAcrossSections()) + U->addSectionLabel(D, A, L); + else + U->addSectionDelta(D, A, L, Sec); +} + +void DwarfDebug::addScopeRangeList(DwarfCompileUnit *TheCU, DIE *ScopeDIE, + const SmallVectorImpl<InsnRange> &Range) { + // Emit offset in .debug_range as a relocatable label. emitDIE will handle + // emitting it appropriately. + MCSymbol *RangeSym = Asm->GetTempSymbol("debug_ranges", GlobalRangeCount++); + + // Under fission, ranges are specified by constant offsets relative to the + // CU's DW_AT_GNU_ranges_base. + if (useSplitDwarf()) + TheCU->addSectionDelta(ScopeDIE, dwarf::DW_AT_ranges, RangeSym, + DwarfDebugRangeSectionSym); + else + addSectionLabel(Asm, TheCU, ScopeDIE, dwarf::DW_AT_ranges, RangeSym, + DwarfDebugRangeSectionSym); + + RangeSpanList List(RangeSym); + for (const InsnRange &R : Range) { + RangeSpan Span(getLabelBeforeInsn(R.first), getLabelAfterInsn(R.second)); + List.addRange(std::move(Span)); + } + + // Add the range list to the set of ranges to be emitted. + TheCU->addRangeList(std::move(List)); +} + // Construct new DW_TAG_lexical_block for this scope and attach // DW_AT_low_pc/DW_AT_high_pc labels. -DIE *DwarfDebug::constructLexicalScopeDIE(CompileUnit *TheCU, +DIE *DwarfDebug::constructLexicalScopeDIE(DwarfCompileUnit *TheCU, LexicalScope *Scope) { if (isLexicalScopeDIENull(Scope)) return 0; @@ -464,29 +487,16 @@ DIE *DwarfDebug::constructLexicalScopeDIE(CompileUnit *TheCU, if (Scope->isAbstractScope()) return ScopeDIE; - const SmallVectorImpl<InsnRange> &Ranges = Scope->getRanges(); - // If we have multiple ranges, emit them into the range section. - if (Ranges.size() > 1) { - // .debug_range section has not been laid out yet. Emit offset in - // .debug_range as a uint, size 4, for now. emitDIE will handle - // DW_AT_ranges appropriately. - TheCU->addUInt(ScopeDIE, dwarf::DW_AT_ranges, dwarf::DW_FORM_data4, - DebugRangeSymbols.size() - * Asm->getDataLayout().getPointerSize()); - for (SmallVectorImpl<InsnRange>::const_iterator RI = Ranges.begin(), - RE = Ranges.end(); RI != RE; ++RI) { - DebugRangeSymbols.push_back(getLabelBeforeInsn(RI->first)); - DebugRangeSymbols.push_back(getLabelAfterInsn(RI->second)); - } + const SmallVectorImpl<InsnRange> &ScopeRanges = Scope->getRanges(); - // Terminate the range list. - DebugRangeSymbols.push_back(NULL); - DebugRangeSymbols.push_back(NULL); + // If we have multiple ranges, emit them into the range section. + if (ScopeRanges.size() > 1) { + addScopeRangeList(TheCU, ScopeDIE, ScopeRanges); return ScopeDIE; } // Construct the address range for this DIE. - SmallVectorImpl<InsnRange>::const_iterator RI = Ranges.begin(); + SmallVectorImpl<InsnRange>::const_iterator RI = ScopeRanges.begin(); MCSymbol *Start = getLabelBeforeInsn(RI->first); MCSymbol *End = getLabelAfterInsn(RI->second); assert(End && "End label should not be null!"); @@ -494,18 +504,17 @@ DIE *DwarfDebug::constructLexicalScopeDIE(CompileUnit *TheCU, assert(Start->isDefined() && "Invalid starting label for an inlined scope!"); assert(End->isDefined() && "Invalid end label for an inlined scope!"); - TheCU->addLabelAddress(ScopeDIE, dwarf::DW_AT_low_pc, Start); - TheCU->addLabelAddress(ScopeDIE, dwarf::DW_AT_high_pc, End); + attachLowHighPC(TheCU, ScopeDIE, Start, End); return ScopeDIE; } // This scope represents inlined body of a function. Construct DIE to // represent this concrete inlined copy of the function. -DIE *DwarfDebug::constructInlinedScopeDIE(CompileUnit *TheCU, +DIE *DwarfDebug::constructInlinedScopeDIE(DwarfCompileUnit *TheCU, LexicalScope *Scope) { - const SmallVectorImpl<InsnRange> &Ranges = Scope->getRanges(); - assert(Ranges.empty() == false && + const SmallVectorImpl<InsnRange> &ScopeRanges = Scope->getRanges(); + assert(!ScopeRanges.empty() && "LexicalScope does not have instruction markers!"); if (!Scope->getScopeNode()) @@ -521,22 +530,11 @@ DIE *DwarfDebug::constructInlinedScopeDIE(CompileUnit *TheCU, DIE *ScopeDIE = new DIE(dwarf::DW_TAG_inlined_subroutine); TheCU->addDIEEntry(ScopeDIE, dwarf::DW_AT_abstract_origin, OriginDIE); - if (Ranges.size() > 1) { - // .debug_range section has not been laid out yet. Emit offset in - // .debug_range as a uint, size 4, for now. emitDIE will handle - // DW_AT_ranges appropriately. - TheCU->addUInt(ScopeDIE, dwarf::DW_AT_ranges, dwarf::DW_FORM_data4, - DebugRangeSymbols.size() - * Asm->getDataLayout().getPointerSize()); - for (SmallVectorImpl<InsnRange>::const_iterator RI = Ranges.begin(), - RE = Ranges.end(); RI != RE; ++RI) { - DebugRangeSymbols.push_back(getLabelBeforeInsn(RI->first)); - DebugRangeSymbols.push_back(getLabelAfterInsn(RI->second)); - } - DebugRangeSymbols.push_back(NULL); - DebugRangeSymbols.push_back(NULL); - } else { - SmallVectorImpl<InsnRange>::const_iterator RI = Ranges.begin(); + // If we have multiple ranges, emit them into the range section. + if (ScopeRanges.size() > 1) + addScopeRangeList(TheCU, ScopeDIE, ScopeRanges); + else { + SmallVectorImpl<InsnRange>::const_iterator RI = ScopeRanges.begin(); MCSymbol *StartLabel = getLabelBeforeInsn(RI->first); MCSymbol *EndLabel = getLabelAfterInsn(RI->second); @@ -547,17 +545,16 @@ DIE *DwarfDebug::constructInlinedScopeDIE(CompileUnit *TheCU, "Invalid starting label for an inlined scope!"); assert(EndLabel->isDefined() && "Invalid end label for an inlined scope!"); - TheCU->addLabelAddress(ScopeDIE, dwarf::DW_AT_low_pc, StartLabel); - TheCU->addLabelAddress(ScopeDIE, dwarf::DW_AT_high_pc, EndLabel); + attachLowHighPC(TheCU, ScopeDIE, StartLabel, EndLabel); } InlinedSubprogramDIEs.insert(OriginDIE); // Add the call site information to the DIE. DILocation DL(Scope->getInlinedAt()); - TheCU->addUInt(ScopeDIE, dwarf::DW_AT_call_file, None, - getOrCreateSourceID(DL.getFilename(), DL.getDirectory(), - TheCU->getUniqueID())); + TheCU->addUInt( + ScopeDIE, dwarf::DW_AT_call_file, None, + TheCU->getOrCreateSourceID(DL.getFilename(), DL.getDirectory())); TheCU->addUInt(ScopeDIE, dwarf::DW_AT_call_line, None, DL.getLineNumber()); // Add name to the name table, we do this here because we're guaranteed @@ -567,37 +564,49 @@ DIE *DwarfDebug::constructInlinedScopeDIE(CompileUnit *TheCU, return ScopeDIE; } -DIE *DwarfDebug::createScopeChildrenDIE(CompileUnit *TheCU, LexicalScope *Scope, - SmallVectorImpl<DIE*> &Children) { - DIE *ObjectPointer = NULL; +DIE *DwarfDebug::createScopeChildrenDIE(DwarfCompileUnit *TheCU, + LexicalScope *Scope, + SmallVectorImpl<DIE *> &Children) { + DIE *ObjectPointer = NULL; // Collect arguments for current function. - if (LScopes.isCurrentFunctionScope(Scope)) - for (unsigned i = 0, N = CurrentFnArguments.size(); i < N; ++i) - if (DbgVariable *ArgDV = CurrentFnArguments[i]) + if (LScopes.isCurrentFunctionScope(Scope)) { + for (DbgVariable *ArgDV : CurrentFnArguments) + if (ArgDV) if (DIE *Arg = - TheCU->constructVariableDIE(*ArgDV, Scope->isAbstractScope())) { + TheCU->constructVariableDIE(*ArgDV, Scope->isAbstractScope())) { Children.push_back(Arg); - if (ArgDV->isObjectPointer()) ObjectPointer = Arg; + if (ArgDV->isObjectPointer()) + ObjectPointer = Arg; } + // If this is a variadic function, add an unspecified parameter. + DISubprogram SP(Scope->getScopeNode()); + DIArray FnArgs = SP.getType().getTypeArray(); + if (FnArgs.getElement(FnArgs.getNumElements() - 1) + .isUnspecifiedParameter()) { + DIE *Ellipsis = new DIE(dwarf::DW_TAG_unspecified_parameters); + Children.push_back(Ellipsis); + } + } + // Collect lexical scope children first. - const SmallVectorImpl<DbgVariable *> &Variables =ScopeVariables.lookup(Scope); - for (unsigned i = 0, N = Variables.size(); i < N; ++i) - if (DIE *Variable = - TheCU->constructVariableDIE(*Variables[i], Scope->isAbstractScope())) { + for (DbgVariable *DV : ScopeVariables.lookup(Scope)) + if (DIE *Variable = TheCU->constructVariableDIE(*DV, + Scope->isAbstractScope())) { Children.push_back(Variable); - if (Variables[i]->isObjectPointer()) ObjectPointer = Variable; + if (DV->isObjectPointer()) + ObjectPointer = Variable; } - const SmallVectorImpl<LexicalScope *> &Scopes = Scope->getChildren(); - for (unsigned j = 0, M = Scopes.size(); j < M; ++j) - if (DIE *Nested = constructScopeDIE(TheCU, Scopes[j])) + for (LexicalScope *LS : Scope->getChildren()) + if (DIE *Nested = constructScopeDIE(TheCU, LS)) Children.push_back(Nested); return ObjectPointer; } // Construct a DIE for this scope. -DIE *DwarfDebug::constructScopeDIE(CompileUnit *TheCU, LexicalScope *Scope) { +DIE *DwarfDebug::constructScopeDIE(DwarfCompileUnit *TheCU, + LexicalScope *Scope) { if (!Scope || !Scope->getScopeNode()) return NULL; @@ -634,10 +643,12 @@ DIE *DwarfDebug::constructScopeDIE(CompileUnit *TheCU, LexicalScope *Scope) { // There is no need to emit empty lexical block DIE. std::pair<ImportedEntityMap::const_iterator, - ImportedEntityMap::const_iterator> Range = std::equal_range( - ScopesWithImportedEntities.begin(), ScopesWithImportedEntities.end(), - std::pair<const MDNode *, const MDNode *>(DS, (const MDNode*)0), - less_first()); + ImportedEntityMap::const_iterator> Range = + std::equal_range( + ScopesWithImportedEntities.begin(), + ScopesWithImportedEntities.end(), + std::pair<const MDNode *, const MDNode *>(DS, (const MDNode *)0), + less_first()); if (Children.empty() && Range.first == Range.second) return NULL; ScopeDIE = constructLexicalScopeDIE(TheCU, Scope); @@ -657,146 +668,55 @@ DIE *DwarfDebug::constructScopeDIE(CompileUnit *TheCU, LexicalScope *Scope) { ObjectPointer = createScopeChildrenDIE(TheCU, Scope, Children); // Add children - for (SmallVectorImpl<DIE *>::iterator I = Children.begin(), - E = Children.end(); I != E; ++I) - ScopeDIE->addChild(*I); + for (DIE *I : Children) + ScopeDIE->addChild(I); if (DS.isSubprogram() && ObjectPointer != NULL) TheCU->addDIEEntry(ScopeDIE, dwarf::DW_AT_object_pointer, ObjectPointer); - if (DS.isSubprogram()) - TheCU->addPubTypes(DISubprogram(DS)); - return ScopeDIE; } -// Look up the source id with the given directory and source file names. -// If none currently exists, create a new id and insert it in the -// SourceIds map. This can update DirectoryNames and SourceFileNames maps -// as well. -unsigned DwarfDebug::getOrCreateSourceID(StringRef FileName, - StringRef DirName, unsigned CUID) { - // If we use .loc in assembly, we can't separate .file entries according to - // compile units. Thus all files will belong to the default compile unit. - - // FIXME: add a better feature test than hasRawTextSupport. Even better, - // extend .file to support this. - if (Asm->TM.hasMCUseLoc() && Asm->OutStreamer.hasRawTextSupport()) - CUID = 0; - - // If FE did not provide a file name, then assume stdin. - if (FileName.empty()) - return getOrCreateSourceID("<stdin>", StringRef(), CUID); - - // TODO: this might not belong here. See if we can factor this better. - if (DirName == CompilationDir) - DirName = ""; - - // FileIDCUMap stores the current ID for the given compile unit. - unsigned SrcId = FileIDCUMap[CUID] + 1; - - // We look up the CUID/file/dir by concatenating them with a zero byte. - SmallString<128> NamePair; - NamePair += utostr(CUID); - NamePair += '\0'; - NamePair += DirName; - NamePair += '\0'; // Zero bytes are not allowed in paths. - NamePair += FileName; - - StringMapEntry<unsigned> &Ent = SourceIdMap.GetOrCreateValue(NamePair, SrcId); - if (Ent.getValue() != SrcId) - return Ent.getValue(); - - FileIDCUMap[CUID] = SrcId; - // Print out a .file directive to specify files for .loc directives. - Asm->OutStreamer.EmitDwarfFileDirective(SrcId, DirName, FileName, CUID); +void DwarfDebug::addGnuPubAttributes(DwarfUnit *U, DIE *D) const { + if (!GenerateGnuPubSections) + return; - return SrcId; + U->addFlag(D, dwarf::DW_AT_GNU_pubnames); } -// Create new CompileUnit for the given metadata node with tag +// Create new DwarfCompileUnit for the given metadata node with tag // DW_TAG_compile_unit. -CompileUnit *DwarfDebug::constructCompileUnit(DICompileUnit DIUnit) { +DwarfCompileUnit *DwarfDebug::constructDwarfCompileUnit(DICompileUnit DIUnit) { StringRef FN = DIUnit.getFilename(); CompilationDir = DIUnit.getDirectory(); DIE *Die = new DIE(dwarf::DW_TAG_compile_unit); - CompileUnit *NewCU = new CompileUnit(GlobalCUIndexCount++, Die, DIUnit, Asm, - this, &InfoHolder); + DwarfCompileUnit *NewCU = new DwarfCompileUnit( + InfoHolder.getUnits().size(), Die, DIUnit, Asm, this, &InfoHolder); + InfoHolder.addUnit(NewCU); - FileIDCUMap[NewCU->getUniqueID()] = 0; - // Call this to emit a .file directive if it wasn't emitted for the source - // file this CU comes from yet. - getOrCreateSourceID(FN, CompilationDir, NewCU->getUniqueID()); + // LTO with assembly output shares a single line table amongst multiple CUs. + // To avoid the compilation directory being ambiguous, let the line table + // explicitly describe the directory of all files, never relying on the + // compilation directory. + if (!Asm->OutStreamer.hasRawTextSupport() || SingleCU) + Asm->OutStreamer.getContext().setMCLineTableCompilationDir( + NewCU->getUniqueID(), CompilationDir); NewCU->addString(Die, dwarf::DW_AT_producer, DIUnit.getProducer()); NewCU->addUInt(Die, dwarf::DW_AT_language, dwarf::DW_FORM_data2, DIUnit.getLanguage()); NewCU->addString(Die, dwarf::DW_AT_name, FN); - // 2.17.1 requires that we use DW_AT_low_pc for a single entry point - // into an entity. We're using 0 (or a NULL label) for this. For - // split dwarf it's in the skeleton CU so omit it here. - if (!useSplitDwarf()) - NewCU->addLabelAddress(Die, dwarf::DW_AT_low_pc, NULL); - - // Define start line table label for each Compile Unit. - MCSymbol *LineTableStartSym = Asm->GetTempSymbol("line_table_start", - NewCU->getUniqueID()); - Asm->OutStreamer.getContext().setMCLineTableSymbol(LineTableStartSym, - NewCU->getUniqueID()); - - // Use a single line table if we are using .loc and generating assembly. - bool UseTheFirstCU = - (Asm->TM.hasMCUseLoc() && Asm->OutStreamer.hasRawTextSupport()) || - (NewCU->getUniqueID() == 0); - if (!useSplitDwarf()) { - // DW_AT_stmt_list is a offset of line number information for this - // compile unit in debug_line section. For split dwarf this is - // left in the skeleton CU and so not included. - // The line table entries are not always emitted in assembly, so it - // is not okay to use line_table_start here. - if (Asm->MAI->doesDwarfUseRelocationsAcrossSections()) - NewCU->addLabel(Die, dwarf::DW_AT_stmt_list, dwarf::DW_FORM_sec_offset, - UseTheFirstCU ? Asm->GetTempSymbol("section_line") - : LineTableStartSym); - else if (UseTheFirstCU) - NewCU->addUInt(Die, dwarf::DW_AT_stmt_list, dwarf::DW_FORM_data4, 0); - else - NewCU->addDelta(Die, dwarf::DW_AT_stmt_list, dwarf::DW_FORM_data4, - LineTableStartSym, DwarfLineSectionSym); + NewCU->initStmtList(DwarfLineSectionSym); // If we're using split dwarf the compilation dir is going to be in the // skeleton CU and so we don't need to duplicate it here. if (!CompilationDir.empty()) NewCU->addString(Die, dwarf::DW_AT_comp_dir, CompilationDir); - // Flags to let the linker know we have emitted new style pubnames. Only - // emit it here if we don't have a skeleton CU for split dwarf. - if (GenerateGnuPubSections) { - if (Asm->MAI->doesDwarfUseRelocationsAcrossSections()) - NewCU->addLabel(Die, dwarf::DW_AT_GNU_pubnames, - dwarf::DW_FORM_sec_offset, - Asm->GetTempSymbol("gnu_pubnames", - NewCU->getUniqueID())); - else - NewCU->addDelta(Die, dwarf::DW_AT_GNU_pubnames, dwarf::DW_FORM_data4, - Asm->GetTempSymbol("gnu_pubnames", - NewCU->getUniqueID()), - DwarfGnuPubNamesSectionSym); - - if (Asm->MAI->doesDwarfUseRelocationsAcrossSections()) - NewCU->addLabel(Die, dwarf::DW_AT_GNU_pubtypes, - dwarf::DW_FORM_sec_offset, - Asm->GetTempSymbol("gnu_pubtypes", - NewCU->getUniqueID())); - else - NewCU->addDelta(Die, dwarf::DW_AT_GNU_pubtypes, dwarf::DW_FORM_data4, - Asm->GetTempSymbol("gnu_pubtypes", - NewCU->getUniqueID()), - DwarfGnuPubTypesSectionSym); - } + addGnuPubAttributes(NewCU, Die); } if (DIUnit.isOptimized()) @@ -808,12 +728,18 @@ CompileUnit *DwarfDebug::constructCompileUnit(DICompileUnit DIUnit) { if (unsigned RVer = DIUnit.getRunTimeVersion()) NewCU->addUInt(Die, dwarf::DW_AT_APPLE_major_runtime_vers, - dwarf::DW_FORM_data1, RVer); + dwarf::DW_FORM_data1, RVer); if (!FirstCU) FirstCU = NewCU; - InfoHolder.addUnit(NewCU); + if (useSplitDwarf()) { + NewCU->initSection(Asm->getObjFileLowering().getDwarfInfoDWOSection(), + DwarfInfoDWOSectionSym); + NewCU->setSkeleton(constructSkeletonCU(NewCU)); + } else + NewCU->initSection(Asm->getObjFileLowering().getDwarfInfoSection(), + DwarfInfoSectionSym); CUMap.insert(std::make_pair(DIUnit, NewCU)); CUDieMap.insert(std::make_pair(Die, NewCU)); @@ -821,12 +747,13 @@ CompileUnit *DwarfDebug::constructCompileUnit(DICompileUnit DIUnit) { } // Construct subprogram DIE. -void DwarfDebug::constructSubprogramDIE(CompileUnit *TheCU, const MDNode *N) { +void DwarfDebug::constructSubprogramDIE(DwarfCompileUnit *TheCU, + const MDNode *N) { // FIXME: We should only call this routine once, however, during LTO if a // program is defined in multiple CUs we could end up calling it out of // beginModule as we walk the CUs. - CompileUnit *&CURef = SPMap[N]; + DwarfCompileUnit *&CURef = SPMap[N]; if (CURef) return; CURef = TheCU; @@ -843,24 +770,22 @@ void DwarfDebug::constructSubprogramDIE(CompileUnit *TheCU, const MDNode *N) { TheCU->addGlobalName(SP.getName(), SubprogramDie, resolve(SP.getContext())); } -void DwarfDebug::constructImportedEntityDIE(CompileUnit *TheCU, +void DwarfDebug::constructImportedEntityDIE(DwarfCompileUnit *TheCU, const MDNode *N) { DIImportedEntity Module(N); - if (!Module.Verify()) - return; + assert(Module.Verify()); if (DIE *D = TheCU->getOrCreateContextDIE(Module.getContext())) constructImportedEntityDIE(TheCU, Module, D); } -void DwarfDebug::constructImportedEntityDIE(CompileUnit *TheCU, const MDNode *N, - DIE *Context) { +void DwarfDebug::constructImportedEntityDIE(DwarfCompileUnit *TheCU, + const MDNode *N, DIE *Context) { DIImportedEntity Module(N); - if (!Module.Verify()) - return; + assert(Module.Verify()); return constructImportedEntityDIE(TheCU, Module, Context); } -void DwarfDebug::constructImportedEntityDIE(CompileUnit *TheCU, +void DwarfDebug::constructImportedEntityDIE(DwarfCompileUnit *TheCU, const DIImportedEntity &Module, DIE *Context) { assert(Module.Verify() && @@ -869,7 +794,7 @@ void DwarfDebug::constructImportedEntityDIE(CompileUnit *TheCU, DIE *IMDie = new DIE(Module.getTag()); TheCU->insertDIE(Module, IMDie); DIE *EntityDie; - DIDescriptor Entity = Module.getEntity(); + DIDescriptor Entity = resolve(Module.getEntity()); if (Entity.isNameSpace()) EntityDie = TheCU->getOrCreateNameSpace(DINameSpace(Entity)); else if (Entity.isSubprogram()) @@ -878,11 +803,9 @@ void DwarfDebug::constructImportedEntityDIE(CompileUnit *TheCU, EntityDie = TheCU->getOrCreateTypeDIE(DIType(Entity)); else EntityDie = TheCU->getDIE(Entity); - unsigned FileID = getOrCreateSourceID(Module.getContext().getFilename(), - Module.getContext().getDirectory(), - TheCU->getUniqueID()); - TheCU->addUInt(IMDie, dwarf::DW_AT_decl_file, None, FileID); - TheCU->addUInt(IMDie, dwarf::DW_AT_decl_line, None, Module.getLineNumber()); + TheCU->addSourceLine(IMDie, Module.getLineNumber(), + Module.getContext().getFilename(), + Module.getContext().getDirectory()); TheCU->addDIEEntry(IMDie, dwarf::DW_AT_import, EntityDie); StringRef Name = Module.getName(); if (!Name.empty()) @@ -909,9 +832,11 @@ void DwarfDebug::beginModule() { // Emit initial sections so we can reference labels later. emitSectionLabels(); - for (unsigned i = 0, e = CU_Nodes->getNumOperands(); i != e; ++i) { - DICompileUnit CUNode(CU_Nodes->getOperand(i)); - CompileUnit *CU = constructCompileUnit(CUNode); + SingleCU = CU_Nodes->getNumOperands() == 1; + + for (MDNode *N : CU_Nodes->operands()) { + DICompileUnit CUNode(N); + DwarfCompileUnit *CU = constructDwarfCompileUnit(CUNode); DIArray ImportedEntities = CUNode.getImportedEntities(); for (unsigned i = 0, e = ImportedEntities.getNumElements(); i != e; ++i) ScopesWithImportedEntities.push_back(std::make_pair( @@ -929,8 +854,13 @@ void DwarfDebug::beginModule() { for (unsigned i = 0, e = EnumTypes.getNumElements(); i != e; ++i) CU->getOrCreateTypeDIE(EnumTypes.getElement(i)); DIArray RetainedTypes = CUNode.getRetainedTypes(); - for (unsigned i = 0, e = RetainedTypes.getNumElements(); i != e; ++i) - CU->getOrCreateTypeDIE(RetainedTypes.getElement(i)); + for (unsigned i = 0, e = RetainedTypes.getNumElements(); i != e; ++i) { + DIType Ty(RetainedTypes.getElement(i)); + // The retained types array by design contains pointers to + // MDNodes rather than DIRefs. Unique them here. + DIType UniqueTy(resolve(Ty.getRef())); + CU->getOrCreateTypeDIE(UniqueTy); + } // Emit imported_modules last so that the relevant context is already // available. for (unsigned i = 0, e = ImportedEntities.getNumElements(); i != e; ++i) @@ -947,14 +877,11 @@ void DwarfDebug::beginModule() { // Attach DW_AT_inline attribute with inlined subprogram DIEs. void DwarfDebug::computeInlinedDIEs() { // Attach DW_AT_inline attribute with inlined subprogram DIEs. - for (SmallPtrSet<DIE *, 4>::iterator AI = InlinedSubprogramDIEs.begin(), - AE = InlinedSubprogramDIEs.end(); AI != AE; ++AI) { - DIE *ISP = *AI; + for (DIE *ISP : InlinedSubprogramDIEs) FirstCU->addUInt(ISP, dwarf::DW_AT_inline, None, dwarf::DW_INL_inlined); - } - for (DenseMap<const MDNode *, DIE *>::iterator AI = AbstractSPDies.begin(), - AE = AbstractSPDies.end(); AI != AE; ++AI) { - DIE *ISP = AI->second; + + for (const auto &AI : AbstractSPDies) { + DIE *ISP = AI.second; if (InlinedSubprogramDIEs.count(ISP)) continue; FirstCU->addUInt(ISP, dwarf::DW_AT_inline, None, dwarf::DW_INL_inlined); @@ -966,8 +893,8 @@ void DwarfDebug::collectDeadVariables() { const Module *M = MMI->getModule(); if (NamedMDNode *CU_Nodes = M->getNamedMetadata("llvm.dbg.cu")) { - for (unsigned i = 0, e = CU_Nodes->getNumOperands(); i != e; ++i) { - DICompileUnit TheCU(CU_Nodes->getOperand(i)); + for (MDNode *N : CU_Nodes->operands()) { + DICompileUnit TheCU(N); DIArray Subprograms = TheCU.getSubprograms(); for (unsigned i = 0, e = Subprograms.getNumElements(); i != e; ++i) { DISubprogram SP(Subprograms.getElement(i)); @@ -982,7 +909,8 @@ void DwarfDebug::collectDeadVariables() { continue; // Construct subprogram DIE and add variables DIEs. - CompileUnit *SPCU = CUMap.lookup(TheCU); + DwarfCompileUnit *SPCU = + static_cast<DwarfCompileUnit *>(CUMap.lookup(TheCU)); assert(SPCU && "Unable to find Compile Unit!"); // FIXME: See the comment in constructSubprogramDIE about duplicate // subprogram DIEs. @@ -993,8 +921,7 @@ void DwarfDebug::collectDeadVariables() { if (!DV.isVariable()) continue; DbgVariable NewVar(DV, NULL, this); - if (DIE *VariableDIE = - SPCU->constructVariableDIE(NewVar, false)) + if (DIE *VariableDIE = SPCU->constructVariableDIE(NewVar, false)) SPDIE->addChild(VariableDIE); } } @@ -1002,41 +929,6 @@ void DwarfDebug::collectDeadVariables() { } } -// Type Signature [7.27] and ODR Hash code. - -/// \brief Grabs the string in whichever attribute is passed in and returns -/// a reference to it. Returns "" if the attribute doesn't exist. -static StringRef getDIEStringAttr(DIE *Die, unsigned Attr) { - DIEValue *V = Die->findAttribute(Attr); - - if (DIEString *S = dyn_cast_or_null<DIEString>(V)) - return S->getString(); - - return StringRef(""); -} - -/// Return true if the current DIE is contained within an anonymous namespace. -static bool isContainedInAnonNamespace(DIE *Die) { - DIE *Parent = Die->getParent(); - - while (Parent) { - if (Parent->getTag() == dwarf::DW_TAG_namespace && - getDIEStringAttr(Parent, dwarf::DW_AT_name) == "") - return true; - Parent = Parent->getParent(); - } - - return false; -} - -/// Test if the current CU language is C++ and that we have -/// a named type that is not contained in an anonymous namespace. -static bool shouldAddODRHash(CompileUnit *CU, DIE *Die) { - return CU->getLanguage() == dwarf::DW_LANG_C_plus_plus && - getDIEStringAttr(Die, dwarf::DW_AT_name) != "" && - !isContainedInAnonNamespace(Die); -} - void DwarfDebug::finalizeModuleInfo() { // Collect info for variables that were optimized out. collectDeadVariables(); @@ -1044,47 +936,67 @@ void DwarfDebug::finalizeModuleInfo() { // Attach DW_AT_inline attribute with inlined subprogram DIEs. computeInlinedDIEs(); - // Split out type units and conditionally add an ODR tag to the split - // out type. - // FIXME: Do type splitting. - for (unsigned i = 0, e = TypeUnits.size(); i != e; ++i) { - DIE *Die = TypeUnits[i]; - DIEHash Hash; - // If we've requested ODR hashes and it's applicable for an ODR hash then - // add the ODR signature now. - // FIXME: This should be added onto the type unit, not the type, but this - // works as an intermediate stage. - if (GenerateODRHash && shouldAddODRHash(CUMap.begin()->second, Die)) - CUMap.begin()->second->addUInt(Die, dwarf::DW_AT_GNU_odr_signature, - dwarf::DW_FORM_data8, - Hash.computeDIEODRSignature(*Die)); - } - - // Handle anything that needs to be done on a per-cu basis. - for (DenseMap<const MDNode *, CompileUnit *>::iterator CUI = CUMap.begin(), - CUE = CUMap.end(); - CUI != CUE; ++CUI) { - CompileUnit *TheCU = CUI->second; + // Handle anything that needs to be done on a per-unit basis after + // all other generation. + for (DwarfUnit *TheU : getUnits()) { // Emit DW_AT_containing_type attribute to connect types with their // vtable holding type. - TheCU->constructContainingTypeDIEs(); - - // If we're splitting the dwarf out now that we've got the entire - // CU then construct a skeleton CU based upon it. - if (useSplitDwarf()) { - uint64_t ID = 0; - if (GenerateCUHash) { - DIEHash CUHash; - ID = CUHash.computeCUSignature(*TheCU->getCUDie()); + TheU->constructContainingTypeDIEs(); + + // Add CU specific attributes if we need to add any. + if (TheU->getUnitDie()->getTag() == dwarf::DW_TAG_compile_unit) { + // If we're splitting the dwarf out now that we've got the entire + // CU then add the dwo id to it. + DwarfCompileUnit *SkCU = + static_cast<DwarfCompileUnit *>(TheU->getSkeleton()); + if (useSplitDwarf()) { + // Emit a unique identifier for this CU. + uint64_t ID = DIEHash(Asm).computeCUSignature(*TheU->getUnitDie()); + TheU->addUInt(TheU->getUnitDie(), dwarf::DW_AT_GNU_dwo_id, + dwarf::DW_FORM_data8, ID); + SkCU->addUInt(SkCU->getUnitDie(), dwarf::DW_AT_GNU_dwo_id, + dwarf::DW_FORM_data8, ID); + + // We don't keep track of which addresses are used in which CU so this + // is a bit pessimistic under LTO. + if (!InfoHolder.getAddrPool()->empty()) + addSectionLabel(Asm, SkCU, SkCU->getUnitDie(), + dwarf::DW_AT_GNU_addr_base, DwarfAddrSectionSym, + DwarfAddrSectionSym); + if (!TheU->getRangeLists().empty()) + addSectionLabel(Asm, SkCU, SkCU->getUnitDie(), + dwarf::DW_AT_GNU_ranges_base, + DwarfDebugRangeSectionSym, DwarfDebugRangeSectionSym); + } + + // If we have code split among multiple sections or non-contiguous + // ranges of code then emit a DW_AT_ranges attribute on the unit that will + // remain in the .o file, otherwise add a DW_AT_low_pc. + // FIXME: We should use ranges allow reordering of code ala + // .subsections_via_symbols in mach-o. This would mean turning on + // ranges for all subprogram DIEs for mach-o. + DwarfCompileUnit *U = SkCU ? SkCU : static_cast<DwarfCompileUnit *>(TheU); + unsigned NumRanges = TheU->getRanges().size(); + if (NumRanges) { + if (NumRanges > 1) { + addSectionLabel(Asm, U, U->getUnitDie(), dwarf::DW_AT_ranges, + Asm->GetTempSymbol("cu_ranges", U->getUniqueID()), + DwarfDebugRangeSectionSym); + + // A DW_AT_low_pc attribute may also be specified in combination with + // DW_AT_ranges to specify the default base address for use in + // location lists (see Section 2.6.2) and range lists (see Section + // 2.17.3). + U->addUInt(U->getUnitDie(), dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr, + 0); + } else { + RangeSpan &Range = TheU->getRanges().back(); + U->addLocalLabelAddress(U->getUnitDie(), dwarf::DW_AT_low_pc, + Range.getStart()); + U->addLabelDelta(U->getUnitDie(), dwarf::DW_AT_high_pc, + Range.getEnd(), Range.getStart()); + } } - // This should be a unique identifier when we want to build .dwp files. - TheCU->addUInt(TheCU->getCUDie(), dwarf::DW_AT_GNU_dwo_id, - dwarf::DW_FORM_data8, ID); - // Now construct the skeleton CU associated. - CompileUnit *SkCU = constructSkeletonCU(TheCU); - // This should be a unique identifier when we want to build .dwp files. - SkCU->addUInt(SkCU->getCUDie(), dwarf::DW_AT_GNU_dwo_id, - dwarf::DW_FORM_data8, ID); } } @@ -1095,9 +1007,8 @@ void DwarfDebug::finalizeModuleInfo() { } void DwarfDebug::endSections() { - // Filter labels by section. - for (size_t n = 0; n < ArangeLabels.size(); n++) { - const SymbolCU &SCU = ArangeLabels[n]; + // Filter labels by section. + for (const SymbolCU &SCU : ArangeLabels) { if (SCU.Sym->isInSection()) { // Make a note of this symbol and it's section. const MCSection *Section = &SCU.Sym->getSection(); @@ -1113,9 +1024,8 @@ void DwarfDebug::endSections() { // Build a list of sections used. std::vector<const MCSection *> Sections; - for (SectionMapType::iterator it = SectionMap.begin(); it != SectionMap.end(); - it++) { - const MCSection *Section = it->first; + for (const auto &it : SectionMap) { + const MCSection *Section = it.first; Sections.push_back(Section); } @@ -1124,15 +1034,15 @@ void DwarfDebug::endSections() { std::sort(Sections.begin(), Sections.end(), SectionSort); // Add terminating symbols for each section. - for (unsigned ID=0;ID<Sections.size();ID++) { + for (unsigned ID = 0, E = Sections.size(); ID != E; ID++) { const MCSection *Section = Sections[ID]; MCSymbol *Sym = NULL; if (Section) { // We can't call MCSection::getLabelEndName, as it's only safe to do so - // if we know the section name up-front. For user-created sections, the resulting - // label may not be valid to use as a label. (section names can use a greater - // set of characters on some systems) + // if we know the section name up-front. For user-created sections, the + // resulting label may not be valid to use as a label. (section names can + // use a greater set of characters on some systems) Sym = Asm->GetTempSymbol("debug_end", ID); Asm->OutStreamer.SwitchSection(Section); Asm->OutStreamer.EmitLabel(Sym); @@ -1145,8 +1055,11 @@ void DwarfDebug::endSections() { // Emit all Dwarf sections that should come after the content. void DwarfDebug::endModule() { + assert(CurFn == 0); + assert(CurMI == 0); - if (!FirstCU) return; + if (!FirstCU) + return; // End any existing sections. // TODO: Does this need to happen? @@ -1155,58 +1068,32 @@ void DwarfDebug::endModule() { // Finalize the debug info for the module. finalizeModuleInfo(); - if (!useSplitDwarf()) { - emitDebugStr(); + emitDebugStr(); - // Emit all the DIEs into a debug info section. - emitDebugInfo(); + // Emit all the DIEs into a debug info section. + emitDebugInfo(); - // Corresponding abbreviations into a abbrev section. - emitAbbreviations(); - - // Emit info into a debug loc section. - emitDebugLoc(); + // Corresponding abbreviations into a abbrev section. + emitAbbreviations(); - // Emit info into a debug aranges section. + // Emit info into a debug aranges section. + if (GenerateARangeSection) emitDebugARanges(); - // Emit info into a debug ranges section. - emitDebugRanges(); - - // Emit info into a debug macinfo section. - emitDebugMacInfo(); + // Emit info into a debug ranges section. + emitDebugRanges(); - } else { - // TODO: Fill this in for separated debug sections and separate - // out information into new sections. - emitDebugStr(); - if (useSplitDwarf()) - emitDebugStrDWO(); - - // Emit the debug info section and compile units. - emitDebugInfo(); + if (useSplitDwarf()) { + emitDebugStrDWO(); emitDebugInfoDWO(); - - // Corresponding abbreviations into a abbrev section. - emitAbbreviations(); emitDebugAbbrevDWO(); - - // Emit info into a debug loc section. - emitDebugLoc(); - - // Emit info into a debug aranges section. - emitDebugARanges(); - - // Emit info into a debug ranges section. - emitDebugRanges(); - - // Emit info into a debug macinfo section. - emitDebugMacInfo(); - + emitDebugLineDWO(); // Emit DWO addresses. InfoHolder.emitAddresses(Asm->getObjFileLowering().getDwarfAddrSection()); - - } + emitDebugLocDWO(); + } else + // Emit info into a debug loc section. + emitDebugLoc(); // Emit info into the dwarf accelerator table sections. if (useDwarfAccelTables()) { @@ -1224,13 +1111,6 @@ void DwarfDebug::endModule() { // clean up. SPMap.clear(); - for (DenseMap<const MDNode *, CompileUnit *>::iterator I = CUMap.begin(), - E = CUMap.end(); I != E; ++I) - delete I->second; - - for (SmallVectorImpl<CompileUnit *>::iterator I = SkeletonCUs.begin(), - E = SkeletonCUs.end(); I != E; ++I) - delete *I; // Reset these for the next Module if we have one. FirstCU = NULL; @@ -1257,8 +1137,7 @@ DbgVariable *DwarfDebug::findAbstractVariable(DIVariable &DV, } // If Var is a current function argument then add it to CurrentFnArguments list. -bool DwarfDebug::addCurrentFnArgument(const MachineFunction *MF, - DbgVariable *Var, LexicalScope *Scope) { +bool DwarfDebug::addCurrentFnArgument(DbgVariable *Var, LexicalScope *Scope) { if (!LScopes.isCurrentFunctionScope(Scope)) return false; DIVariable DV = Var->getVariable(); @@ -1270,7 +1149,7 @@ bool DwarfDebug::addCurrentFnArgument(const MachineFunction *MF, size_t Size = CurrentFnArguments.size(); if (Size == 0) - CurrentFnArguments.resize(MF->getFunction()->arg_size()); + CurrentFnArguments.resize(CurFn->getFunction()->arg_size()); // llvm::Function argument size is not good indicator of how many // arguments does the function have at source level. if (ArgNo > Size) @@ -1280,31 +1159,26 @@ bool DwarfDebug::addCurrentFnArgument(const MachineFunction *MF, } // Collect variable information from side table maintained by MMI. -void -DwarfDebug::collectVariableInfoFromMMITable(const MachineFunction *MF, - SmallPtrSet<const MDNode *, 16> &Processed) { - MachineModuleInfo::VariableDbgInfoMapTy &VMap = MMI->getVariableDbgInfo(); - for (MachineModuleInfo::VariableDbgInfoMapTy::iterator VI = VMap.begin(), - VE = VMap.end(); VI != VE; ++VI) { - const MDNode *Var = VI->first; - if (!Var) continue; - Processed.insert(Var); - DIVariable DV(Var); - const std::pair<unsigned, DebugLoc> &VP = VI->second; - - LexicalScope *Scope = LScopes.findLexicalScope(VP.second); +void DwarfDebug::collectVariableInfoFromMMITable( + SmallPtrSet<const MDNode *, 16> &Processed) { + for (const auto &VI : MMI->getVariableDbgInfo()) { + if (!VI.Var) + continue; + Processed.insert(VI.Var); + DIVariable DV(VI.Var); + LexicalScope *Scope = LScopes.findLexicalScope(VI.Loc); // If variable scope is not found then skip this variable. if (Scope == 0) continue; - DbgVariable *AbsDbgVariable = findAbstractVariable(DV, VP.second); + DbgVariable *AbsDbgVariable = findAbstractVariable(DV, VI.Loc); DbgVariable *RegVar = new DbgVariable(DV, AbsDbgVariable, this); - RegVar->setFrameIndex(VP.first); - if (!addCurrentFnArgument(MF, RegVar, Scope)) + RegVar->setFrameIndex(VI.Slot); + if (!addCurrentFnArgument(RegVar, Scope)) addScopeVariable(Scope, RegVar); if (AbsDbgVariable) - AbsDbgVariable->setFrameIndex(VP.first); + AbsDbgVariable->setFrameIndex(VI.Slot); } } @@ -1312,18 +1186,19 @@ DwarfDebug::collectVariableInfoFromMMITable(const MachineFunction *MF, // defined reg. static bool isDbgValueInDefinedReg(const MachineInstr *MI) { assert(MI->isDebugValue() && "Invalid DBG_VALUE machine instruction!"); - return MI->getNumOperands() == 3 && - MI->getOperand(0).isReg() && MI->getOperand(0).getReg() && + return MI->getNumOperands() == 3 && MI->getOperand(0).isReg() && + MI->getOperand(0).getReg() && (MI->getOperand(1).isImm() || (MI->getOperand(1).isReg() && MI->getOperand(1).getReg() == 0U)); } // Get .debug_loc entry for the instruction range starting at MI. -static DotDebugLocEntry getDebugLocEntry(AsmPrinter *Asm, - const MCSymbol *FLabel, - const MCSymbol *SLabel, - const MachineInstr *MI) { - const MDNode *Var = MI->getOperand(MI->getNumOperands() - 1).getMetadata(); +static DebugLocEntry getDebugLocEntry(AsmPrinter *Asm, + const MCSymbol *FLabel, + const MCSymbol *SLabel, + const MachineInstr *MI, + DwarfCompileUnit *Unit) { + const MDNode *Var = MI->getOperand(MI->getNumOperands() - 1).getMetadata(); assert(MI->getNumOperands() == 3); if (MI->getOperand(0).isReg()) { @@ -1334,36 +1209,32 @@ static DotDebugLocEntry getDebugLocEntry(AsmPrinter *Asm, MLoc.set(MI->getOperand(0).getReg()); else MLoc.set(MI->getOperand(0).getReg(), MI->getOperand(1).getImm()); - return DotDebugLocEntry(FLabel, SLabel, MLoc, Var); + return DebugLocEntry(FLabel, SLabel, MLoc, Var, Unit); } if (MI->getOperand(0).isImm()) - return DotDebugLocEntry(FLabel, SLabel, MI->getOperand(0).getImm()); + return DebugLocEntry(FLabel, SLabel, MI->getOperand(0).getImm(), Unit); if (MI->getOperand(0).isFPImm()) - return DotDebugLocEntry(FLabel, SLabel, MI->getOperand(0).getFPImm()); + return DebugLocEntry(FLabel, SLabel, MI->getOperand(0).getFPImm(), Unit); if (MI->getOperand(0).isCImm()) - return DotDebugLocEntry(FLabel, SLabel, MI->getOperand(0).getCImm()); + return DebugLocEntry(FLabel, SLabel, MI->getOperand(0).getCImm(), Unit); llvm_unreachable("Unexpected 3 operand DBG_VALUE instruction!"); } // Find variables for each lexical scope. void -DwarfDebug::collectVariableInfo(const MachineFunction *MF, - SmallPtrSet<const MDNode *, 16> &Processed) { +DwarfDebug::collectVariableInfo(SmallPtrSet<const MDNode *, 16> &Processed) { // Grab the variable info that was squirreled away in the MMI side-table. - collectVariableInfoFromMMITable(MF, Processed); + collectVariableInfoFromMMITable(Processed); - for (SmallVectorImpl<const MDNode*>::const_iterator - UVI = UserVariables.begin(), UVE = UserVariables.end(); UVI != UVE; - ++UVI) { - const MDNode *Var = *UVI; + for (const MDNode *Var : UserVariables) { if (Processed.count(Var)) continue; // History contains relevant DBG_VALUE instructions for Var and instructions // clobbering it. - SmallVectorImpl<const MachineInstr*> &History = DbgValues[Var]; + SmallVectorImpl<const MachineInstr *> &History = DbgValues[Var]; if (History.empty()) continue; const MachineInstr *MInsn = History.front(); @@ -1371,7 +1242,7 @@ DwarfDebug::collectVariableInfo(const MachineFunction *MF, DIVariable DV(Var); LexicalScope *Scope = NULL; if (DV.getTag() == dwarf::DW_TAG_arg_variable && - DISubprogram(DV.getContext()).describes(MF->getFunction())) + DISubprogram(DV.getContext()).describes(CurFn->getFunction())) Scope = LScopes.getCurrentFunctionScope(); else if (MDNode *IA = DV.getInlinedAt()) Scope = LScopes.findInlinedScope(DebugLoc::getFromDILocation(IA)); @@ -1385,14 +1256,14 @@ DwarfDebug::collectVariableInfo(const MachineFunction *MF, assert(MInsn->isDebugValue() && "History must begin with debug value"); DbgVariable *AbsVar = findAbstractVariable(DV, MInsn->getDebugLoc()); DbgVariable *RegVar = new DbgVariable(DV, AbsVar, this); - if (!addCurrentFnArgument(MF, RegVar, Scope)) + if (!addCurrentFnArgument(RegVar, Scope)) addScopeVariable(Scope, RegVar); if (AbsVar) AbsVar->setMInsn(MInsn); // Simplify ranges that are fully coalesced. - if (History.size() <= 1 || (History.size() == 2 && - MInsn->isIdenticalTo(History.back()))) { + if (History.size() <= 1 || + (History.size() == 2 && MInsn->isIdenticalTo(History.back()))) { RegVar->setMInsn(MInsn); continue; } @@ -1400,14 +1271,21 @@ DwarfDebug::collectVariableInfo(const MachineFunction *MF, // Handle multiple DBG_VALUE instructions describing one variable. RegVar->setDotDebugLocOffset(DotDebugLocEntries.size()); - for (SmallVectorImpl<const MachineInstr*>::const_iterator - HI = History.begin(), HE = History.end(); HI != HE; ++HI) { + DotDebugLocEntries.resize(DotDebugLocEntries.size() + 1); + DebugLocList &LocList = DotDebugLocEntries.back(); + LocList.Label = + Asm->GetTempSymbol("debug_loc", DotDebugLocEntries.size() - 1); + SmallVector<DebugLocEntry, 4> &DebugLoc = LocList.List; + for (SmallVectorImpl<const MachineInstr *>::const_iterator + HI = History.begin(), + HE = History.end(); + HI != HE; ++HI) { const MachineInstr *Begin = *HI; assert(Begin->isDebugValue() && "Invalid History entry"); // Check if DBG_VALUE is truncating a range. - if (Begin->getNumOperands() > 1 && Begin->getOperand(0).isReg() - && !Begin->getOperand(0).getReg()) + if (Begin->getNumOperands() > 1 && Begin->getOperand(0).isReg() && + !Begin->getOperand(0).getReg()) continue; // Compute the range for a register location. @@ -1421,7 +1299,7 @@ DwarfDebug::collectVariableInfo(const MachineFunction *MF, else { const MachineInstr *End = HI[1]; DEBUG(dbgs() << "DotDebugLoc Pair:\n" - << "\t" << *Begin << "\t" << *End << "\n"); + << "\t" << *Begin << "\t" << *End << "\n"); if (End->isDebugValue()) SLabel = getLabelBeforeInsn(End); else { @@ -1433,10 +1311,12 @@ DwarfDebug::collectVariableInfo(const MachineFunction *MF, } // The value is valid until the next DBG_VALUE or clobber. - DotDebugLocEntries.push_back(getDebugLocEntry(Asm, FLabel, SLabel, - Begin)); + LexicalScope *FnScope = LScopes.getCurrentFunctionScope(); + DwarfCompileUnit *TheCU = SPMap.lookup(FnScope->getScopeNode()); + DebugLocEntry Loc = getDebugLocEntry(Asm, FLabel, SLabel, Begin, TheCU); + if (DebugLoc.empty() || !DebugLoc.back().Merge(Loc)) + DebugLoc.push_back(std::move(Loc)); } - DotDebugLocEntries.push_back(DotDebugLocEntry()); } // Collect info for variables that were optimized out. @@ -1465,6 +1345,8 @@ MCSymbol *DwarfDebug::getLabelAfterInsn(const MachineInstr *MI) { // Process beginning of an instruction. void DwarfDebug::beginInstruction(const MachineInstr *MI) { + assert(CurMI == 0); + CurMI = MI; // Check if source location changes, but ignore DBG_VALUE locations. if (!MI->isDebugValue()) { DebugLoc DL = MI->getDebugLoc(); @@ -1487,8 +1369,8 @@ void DwarfDebug::beginInstruction(const MachineInstr *MI) { } // Insert labels where requested. - DenseMap<const MachineInstr*, MCSymbol*>::iterator I = - LabelsBeforeInsn.find(MI); + DenseMap<const MachineInstr *, MCSymbol *>::iterator I = + LabelsBeforeInsn.find(MI); // No label needed. if (I == LabelsBeforeInsn.end()) @@ -1506,14 +1388,16 @@ void DwarfDebug::beginInstruction(const MachineInstr *MI) { } // Process end of an instruction. -void DwarfDebug::endInstruction(const MachineInstr *MI) { +void DwarfDebug::endInstruction() { + assert(CurMI != 0); // Don't create a new label after DBG_VALUE instructions. // They don't generate code. - if (!MI->isDebugValue()) + if (!CurMI->isDebugValue()) PrevLabel = 0; - DenseMap<const MachineInstr*, MCSymbol*>::iterator I = - LabelsAfterInsn.find(MI); + DenseMap<const MachineInstr *, MCSymbol *>::iterator I = + LabelsAfterInsn.find(CurMI); + CurMI = 0; // No label needed. if (I == LabelsAfterInsn.end()) @@ -1543,53 +1427,24 @@ void DwarfDebug::identifyScopeMarkers() { const SmallVectorImpl<LexicalScope *> &Children = S->getChildren(); if (!Children.empty()) - for (SmallVectorImpl<LexicalScope *>::const_iterator SI = Children.begin(), - SE = Children.end(); SI != SE; ++SI) - WorkList.push_back(*SI); + WorkList.append(Children.begin(), Children.end()); if (S->isAbstractScope()) continue; - const SmallVectorImpl<InsnRange> &Ranges = S->getRanges(); - if (Ranges.empty()) - continue; - for (SmallVectorImpl<InsnRange>::const_iterator RI = Ranges.begin(), - RE = Ranges.end(); RI != RE; ++RI) { - assert(RI->first && "InsnRange does not have first instruction!"); - assert(RI->second && "InsnRange does not have second instruction!"); - requestLabelBeforeInsn(RI->first); - requestLabelAfterInsn(RI->second); + for (const InsnRange &R : S->getRanges()) { + assert(R.first && "InsnRange does not have first instruction!"); + assert(R.second && "InsnRange does not have second instruction!"); + requestLabelBeforeInsn(R.first); + requestLabelAfterInsn(R.second); } } } -// Get MDNode for DebugLoc's scope. -static MDNode *getScopeNode(DebugLoc DL, const LLVMContext &Ctx) { - if (MDNode *InlinedAt = DL.getInlinedAt(Ctx)) - return getScopeNode(DebugLoc::getFromDILocation(InlinedAt), Ctx); - return DL.getScope(Ctx); -} - -// Walk up the scope chain of given debug loc and find line number info -// for the function. -static DebugLoc getFnDebugLoc(DebugLoc DL, const LLVMContext &Ctx) { - const MDNode *Scope = getScopeNode(DL, Ctx); - DISubprogram SP = getDISubprogram(Scope); - if (SP.isSubprogram()) { - // Check for number of operands since the compatibility is - // cheap here. - if (SP->getNumOperands() > 19) - return DebugLoc::get(SP.getScopeLineNumber(), 0, SP); - else - return DebugLoc::get(SP.getLineNumber(), 0, SP); - } - - return DebugLoc(); -} - // Gather pre-function debug information. Assumes being called immediately // after the function entry point has been emitted. void DwarfDebug::beginFunction(const MachineFunction *MF) { + CurFn = MF; // If there's no debug info for the function we're not going to do anything. if (!MMI->hasDebugInfo()) @@ -1606,14 +1461,14 @@ void DwarfDebug::beginFunction(const MachineFunction *MF) { // Make sure that each lexical scope will have a begin/end label. identifyScopeMarkers(); - // Set DwarfCompileUnitID in MCContext to the Compile Unit this function + // Set DwarfDwarfCompileUnitID in MCContext to the Compile Unit this function // belongs to so that we add to the correct per-cu line table in the // non-asm case. LexicalScope *FnScope = LScopes.getCurrentFunctionScope(); - CompileUnit *TheCU = SPMap.lookup(FnScope->getScopeNode()); + DwarfCompileUnit *TheCU = SPMap.lookup(FnScope->getScopeNode()); assert(TheCU && "Unable to find compile unit!"); - if (Asm->TM.hasMCUseLoc() && Asm->OutStreamer.hasRawTextSupport()) - // Use a single line table if we are using .loc and generating assembly. + if (Asm->OutStreamer.hasRawTextSupport()) + // Use a single line table if we are generating assembly. Asm->OutStreamer.getContext().setDwarfCompileUnitID(0); else Asm->OutStreamer.getContext().setDwarfCompileUnitID(TheCU->getUniqueID()); @@ -1670,7 +1525,7 @@ void DwarfDebug::beginFunction(const MachineFunction *MF) { // Terminate old register assignments that don't reach MI; MachineFunction::const_iterator PrevMBB = Prev->getParent(); - if (PrevMBB != I && (!AtBlockEntry || llvm::next(PrevMBB) != I) && + if (PrevMBB != I && (!AtBlockEntry || std::next(PrevMBB) != I) && isDbgValueInDefinedReg(Prev)) { // Previous register assignment needs to terminate at the end of // its basic block. @@ -1681,7 +1536,7 @@ void DwarfDebug::beginFunction(const MachineFunction *MF) { DEBUG(dbgs() << "Dropping DBG_VALUE for empty range:\n" << "\t" << *Prev << "\n"); History.pop_back(); - } else if (llvm::next(PrevMBB) != PrevMBB->getParent()->end()) + } else if (std::next(PrevMBB) != PrevMBB->getParent()->end()) // Terminate after LastMI. History.push_back(LastMI); } @@ -1690,7 +1545,7 @@ void DwarfDebug::beginFunction(const MachineFunction *MF) { History.push_back(MI); } else { // Not a DBG_VALUE instruction. - if (!MI->isLabel()) + if (!MI->isPosition()) AtBlockEntry = false; // First known non-DBG_VALUE and non-frame setup location marks @@ -1700,12 +1555,10 @@ void DwarfDebug::beginFunction(const MachineFunction *MF) { PrologEndLoc = MI->getDebugLoc(); // Check if the instruction clobbers any registers with debug vars. - for (MachineInstr::const_mop_iterator MOI = MI->operands_begin(), - MOE = MI->operands_end(); - MOI != MOE; ++MOI) { - if (!MOI->isReg() || !MOI->isDef() || !MOI->getReg()) + for (const MachineOperand &MO : MI->operands()) { + if (!MO.isReg() || !MO.isDef() || !MO.getReg()) continue; - for (MCRegAliasIterator AI(MOI->getReg(), TRI, true); AI.isValid(); + for (MCRegAliasIterator AI(MO.getReg(), TRI, true); AI.isValid(); ++AI) { unsigned Reg = *AI; const MDNode *Var = LiveUserVar[Reg]; @@ -1738,9 +1591,8 @@ void DwarfDebug::beginFunction(const MachineFunction *MF) { } } - for (DbgValueHistoryMap::iterator I = DbgValues.begin(), E = DbgValues.end(); - I != E; ++I) { - SmallVectorImpl<const MachineInstr *> &History = I->second; + for (auto &I : DbgValues) { + SmallVectorImpl<const MachineInstr *> &History = I.second; if (History.empty()) continue; @@ -1759,8 +1611,7 @@ void DwarfDebug::beginFunction(const MachineFunction *MF) { } } // Request labels for the full history. - for (unsigned i = 0, e = History.size(); i != e; ++i) { - const MachineInstr *MI = History[i]; + for (const MachineInstr *MI : History) { if (MI->isDebugValue()) requestLabelBeforeInsn(MI); else @@ -1774,7 +1625,7 @@ void DwarfDebug::beginFunction(const MachineFunction *MF) { // Record beginning of function. if (!PrologEndLoc.isUnknown()) { DebugLoc FnStartDL = - getFnDebugLoc(PrologEndLoc, MF->getFunction()->getContext()); + PrologEndLoc.getFnDebugLoc(MF->getFunction()->getContext()); recordSourceLine( FnStartDL.getLine(), FnStartDL.getCol(), FnStartDL.getScope(MF->getFunction()->getContext()), @@ -1817,27 +1668,42 @@ void DwarfDebug::addScopeVariable(LexicalScope *LS, DbgVariable *Var) { // Gather and emit post-function debug information. void DwarfDebug::endFunction(const MachineFunction *MF) { - if (!MMI->hasDebugInfo() || LScopes.empty()) return; + // Every beginFunction(MF) call should be followed by an endFunction(MF) call, + // though the beginFunction may not be called at all. + // We should handle both cases. + if (CurFn == 0) + CurFn = MF; + else + assert(CurFn == MF); + assert(CurFn != 0); + + if (!MMI->hasDebugInfo() || LScopes.empty()) { + // If we don't have a lexical scope for this function then there will + // be a hole in the range information. Keep note of this by setting the + // previously used section to nullptr. + PrevSection = nullptr; + PrevCU = nullptr; + CurFn = 0; + return; + } // Define end label for subprogram. - FunctionEndSym = Asm->GetTempSymbol("func_end", - Asm->getFunctionNumber()); + FunctionEndSym = Asm->GetTempSymbol("func_end", Asm->getFunctionNumber()); // Assumes in correct section after the entry point. Asm->OutStreamer.EmitLabel(FunctionEndSym); - // Set DwarfCompileUnitID in MCContext to default value. + + // Set DwarfDwarfCompileUnitID in MCContext to default value. Asm->OutStreamer.getContext().setDwarfCompileUnitID(0); SmallPtrSet<const MDNode *, 16> ProcessedVars; - collectVariableInfo(MF, ProcessedVars); + collectVariableInfo(ProcessedVars); LexicalScope *FnScope = LScopes.getCurrentFunctionScope(); - CompileUnit *TheCU = SPMap.lookup(FnScope->getScopeNode()); + DwarfCompileUnit *TheCU = SPMap.lookup(FnScope->getScopeNode()); assert(TheCU && "Unable to find compile unit!"); // Construct abstract scopes. - ArrayRef<LexicalScope *> AList = LScopes.getAbstractScopesList(); - for (unsigned i = 0, e = AList.size(); i != e; ++i) { - LexicalScope *AScope = AList[i]; + for (LexicalScope *AScope : LScopes.getAbstractScopesList()) { DISubprogram SP(AScope->getScopeNode()); if (SP.isSubprogram()) { // Collect info for variables that were optimized out. @@ -1861,14 +1727,18 @@ void DwarfDebug::endFunction(const MachineFunction *MF) { } DIE *CurFnDIE = constructScopeDIE(TheCU, FnScope); - - if (!MF->getTarget().Options.DisableFramePointerElim(*MF)) + if (!CurFn->getTarget().Options.DisableFramePointerElim(*CurFn)) TheCU->addFlag(CurFnDIE, dwarf::DW_AT_APPLE_omit_frame_ptr); + // Add the range of this function to the list of ranges for the CU. + RangeSpan Span(FunctionBeginSym, FunctionEndSym); + TheCU->addRange(std::move(Span)); + PrevSection = Asm->getCurrentSection(); + PrevCU = TheCU; + // Clear debug info - for (ScopeVariablesMap::iterator - I = ScopeVariables.begin(), E = ScopeVariables.end(); I != E; ++I) - DeleteContainerPointers(I->second); + for (auto &I : ScopeVariables) + DeleteContainerPointers(I.second); ScopeVariables.clear(); DeleteContainerPointers(CurrentFnArguments); UserVariables.clear(); @@ -1877,6 +1747,7 @@ void DwarfDebug::endFunction(const MachineFunction *MF) { LabelsBeforeInsn.clear(); LabelsAfterInsn.clear(); PrevLabel = NULL; + CurFn = 0; } // Register a source line with debug info. Returns the unique label that was @@ -1886,6 +1757,7 @@ void DwarfDebug::recordSourceLine(unsigned Line, unsigned Col, const MDNode *S, StringRef Fn; StringRef Dir; unsigned Src = 1; + unsigned Discriminator = 0; if (S) { DIDescriptor Scope(S); @@ -1909,13 +1781,16 @@ void DwarfDebug::recordSourceLine(unsigned Line, unsigned Col, const MDNode *S, DILexicalBlock DB(S); Fn = DB.getFilename(); Dir = DB.getDirectory(); + Discriminator = DB.getDiscriminator(); } else llvm_unreachable("Unexpected scope info"); - Src = getOrCreateSourceID(Fn, Dir, - Asm->OutStreamer.getContext().getDwarfCompileUnitID()); + unsigned CUID = Asm->OutStreamer.getContext().getDwarfCompileUnitID(); + Src = static_cast<DwarfCompileUnit *>(InfoHolder.getUnits()[CUID]) + ->getOrCreateSourceID(Fn, Dir); } - Asm->OutStreamer.EmitDwarfLocDirective(Src, Line, Col, Flags, 0, 0, Fn); + Asm->OutStreamer.EmitDwarfLocDirective(Src, Line, Col, Flags, 0, + Discriminator, Fn); } //===----------------------------------------------------------------------===// @@ -1924,39 +1799,36 @@ void DwarfDebug::recordSourceLine(unsigned Line, unsigned Col, const MDNode *S, // Compute the size and offset of a DIE. The offset is relative to start of the // CU. It returns the offset after laying out the DIE. -unsigned -DwarfUnits::computeSizeAndOffset(DIE *Die, unsigned Offset) { - // Get the children. - const std::vector<DIE *> &Children = Die->getChildren(); - +unsigned DwarfFile::computeSizeAndOffset(DIE *Die, unsigned Offset) { // Record the abbreviation. assignAbbrevNumber(Die->getAbbrev()); // Get the abbreviation for this DIE. - unsigned AbbrevNumber = Die->getAbbrevNumber(); - const DIEAbbrev *Abbrev = Abbreviations[AbbrevNumber - 1]; + const DIEAbbrev &Abbrev = Die->getAbbrev(); // Set DIE offset Die->setOffset(Offset); // Start the size with the size of abbreviation code. - Offset += MCAsmInfo::getULEB128Size(AbbrevNumber); + Offset += getULEB128Size(Die->getAbbrevNumber()); - const SmallVectorImpl<DIEValue*> &Values = Die->getValues(); - const SmallVectorImpl<DIEAbbrevData> &AbbrevData = Abbrev->getData(); + const SmallVectorImpl<DIEValue *> &Values = Die->getValues(); + const SmallVectorImpl<DIEAbbrevData> &AbbrevData = Abbrev.getData(); // Size the DIE attribute values. for (unsigned i = 0, N = Values.size(); i < N; ++i) // Size attribute value. Offset += Values[i]->SizeOf(Asm, AbbrevData[i].getForm()); + // Get the children. + const std::vector<DIE *> &Children = Die->getChildren(); + // Size the DIE children if any. if (!Children.empty()) { - assert(Abbrev->getChildrenFlag() == dwarf::DW_CHILDREN_yes && - "Children flag not set"); + assert(Abbrev.hasChildren() && "Children flag not set"); - for (unsigned j = 0, M = Children.size(); j < M; ++j) - Offset = computeSizeAndOffset(Children[j], Offset); + for (DIE *Child : Children) + Offset = computeSizeAndOffset(Child, Offset); // End of children marker. Offset += sizeof(int8_t); @@ -1967,23 +1839,22 @@ DwarfUnits::computeSizeAndOffset(DIE *Die, unsigned Offset) { } // Compute the size and offset for each DIE. -void DwarfUnits::computeSizeAndOffsets() { +void DwarfFile::computeSizeAndOffsets() { // Offset from the first CU in the debug info section is 0 initially. unsigned SecOffset = 0; // Iterate over each compile unit and set the size and offsets for each // DIE within each compile unit. All offsets are CU relative. - for (SmallVectorImpl<CompileUnit *>::iterator I = CUs.begin(), - E = CUs.end(); I != E; ++I) { - (*I)->setDebugInfoOffset(SecOffset); + for (DwarfUnit *TheU : CUs) { + TheU->setDebugInfoOffset(SecOffset); // CU-relative offset is reset to 0 here. - unsigned Offset = sizeof(int32_t) + // Length of Unit Info - (*I)->getHeaderSize(); // Unit-specific headers + unsigned Offset = sizeof(int32_t) + // Length of Unit Info + TheU->getHeaderSize(); // Unit-specific headers // EndOffset here is CU-relative, after laying out // all of the CU DIE. - unsigned EndOffset = computeSizeAndOffset((*I)->getCUDie(), Offset); + unsigned EndOffset = computeSizeAndOffset(TheU->getUnitDie(), Offset); SecOffset += EndOffset; } } @@ -1994,21 +1865,20 @@ void DwarfDebug::emitSectionLabels() { // Dwarf sections base addresses. DwarfInfoSectionSym = - emitSectionSym(Asm, TLOF.getDwarfInfoSection(), "section_info"); + emitSectionSym(Asm, TLOF.getDwarfInfoSection(), "section_info"); + if (useSplitDwarf()) + DwarfInfoDWOSectionSym = + emitSectionSym(Asm, TLOF.getDwarfInfoDWOSection(), "section_info_dwo"); DwarfAbbrevSectionSym = - emitSectionSym(Asm, TLOF.getDwarfAbbrevSection(), "section_abbrev"); + emitSectionSym(Asm, TLOF.getDwarfAbbrevSection(), "section_abbrev"); if (useSplitDwarf()) - DwarfAbbrevDWOSectionSym = - emitSectionSym(Asm, TLOF.getDwarfAbbrevDWOSection(), - "section_abbrev_dwo"); - emitSectionSym(Asm, TLOF.getDwarfARangesSection()); - - if (const MCSection *MacroInfo = TLOF.getDwarfMacroInfoSection()) - emitSectionSym(Asm, MacroInfo); + DwarfAbbrevDWOSectionSym = emitSectionSym( + Asm, TLOF.getDwarfAbbrevDWOSection(), "section_abbrev_dwo"); + if (GenerateARangeSection) + emitSectionSym(Asm, TLOF.getDwarfARangesSection()); DwarfLineSectionSym = - emitSectionSym(Asm, TLOF.getDwarfLineSection(), "section_line"); - emitSectionSym(Asm, TLOF.getDwarfLocSection()); + emitSectionSym(Asm, TLOF.getDwarfLineSection(), "section_line"); if (GenerateGnuPubSections) { DwarfGnuPubNamesSectionSym = emitSectionSym(Asm, TLOF.getDwarfGnuPubNamesSection()); @@ -2020,39 +1890,36 @@ void DwarfDebug::emitSectionLabels() { } DwarfStrSectionSym = - emitSectionSym(Asm, TLOF.getDwarfStrSection(), "info_string"); + emitSectionSym(Asm, TLOF.getDwarfStrSection(), "info_string"); if (useSplitDwarf()) { DwarfStrDWOSectionSym = - emitSectionSym(Asm, TLOF.getDwarfStrDWOSection(), "skel_string"); + emitSectionSym(Asm, TLOF.getDwarfStrDWOSection(), "skel_string"); DwarfAddrSectionSym = - emitSectionSym(Asm, TLOF.getDwarfAddrSection(), "addr_sec"); - } - DwarfDebugRangeSectionSym = emitSectionSym(Asm, TLOF.getDwarfRangesSection(), - "debug_range"); - - DwarfDebugLocSectionSym = emitSectionSym(Asm, TLOF.getDwarfLocSection(), - "section_debug_loc"); - - TextSectionSym = emitSectionSym(Asm, TLOF.getTextSection(), "text_begin"); - emitSectionSym(Asm, TLOF.getDataSection()); + emitSectionSym(Asm, TLOF.getDwarfAddrSection(), "addr_sec"); + DwarfDebugLocSectionSym = + emitSectionSym(Asm, TLOF.getDwarfLocDWOSection(), "skel_loc"); + } else + DwarfDebugLocSectionSym = + emitSectionSym(Asm, TLOF.getDwarfLocSection(), "section_debug_loc"); + DwarfDebugRangeSectionSym = + emitSectionSym(Asm, TLOF.getDwarfRangesSection(), "debug_range"); } // Recursively emits a debug information entry. -void DwarfDebug::emitDIE(DIE *Die, ArrayRef<DIEAbbrev *> Abbrevs) { +void DwarfDebug::emitDIE(DIE *Die) { // Get the abbreviation for this DIE. - unsigned AbbrevNumber = Die->getAbbrevNumber(); - const DIEAbbrev *Abbrev = Abbrevs[AbbrevNumber - 1]; + const DIEAbbrev &Abbrev = Die->getAbbrev(); // Emit the code (index) for the abbreviation. if (Asm->isVerbose()) - Asm->OutStreamer.AddComment("Abbrev [" + Twine(AbbrevNumber) + "] 0x" + - Twine::utohexstr(Die->getOffset()) + ":0x" + - Twine::utohexstr(Die->getSize()) + " " + - dwarf::TagString(Abbrev->getTag())); - Asm->EmitULEB128(AbbrevNumber); + Asm->OutStreamer.AddComment("Abbrev [" + Twine(Abbrev.getNumber()) + + "] 0x" + Twine::utohexstr(Die->getOffset()) + + ":0x" + Twine::utohexstr(Die->getSize()) + " " + + dwarf::TagString(Abbrev.getTag())); + Asm->EmitULEB128(Abbrev.getNumber()); - const SmallVectorImpl<DIEValue*> &Values = Die->getValues(); - const SmallVectorImpl<DIEAbbrevData> &AbbrevData = Abbrev->getData(); + const SmallVectorImpl<DIEValue *> &Values = Die->getValues(); + const SmallVectorImpl<DIEAbbrevData> &AbbrevData = Abbrev.getData(); // Emit the DIE attribute values. for (unsigned i = 0, N = Values.size(); i < N; ++i) { @@ -2060,159 +1927,73 @@ void DwarfDebug::emitDIE(DIE *Die, ArrayRef<DIEAbbrev *> Abbrevs) { dwarf::Form Form = AbbrevData[i].getForm(); assert(Form && "Too many attributes for DIE (check abbreviation)"); - if (Asm->isVerbose()) + if (Asm->isVerbose()) { Asm->OutStreamer.AddComment(dwarf::AttributeString(Attr)); - - switch (Attr) { - case dwarf::DW_AT_abstract_origin: - case dwarf::DW_AT_type: - case dwarf::DW_AT_friend: - case dwarf::DW_AT_specification: - case dwarf::DW_AT_import: - case dwarf::DW_AT_containing_type: { - DIEEntry *E = cast<DIEEntry>(Values[i]); - DIE *Origin = E->getEntry(); - unsigned Addr = Origin->getOffset(); - if (Form == dwarf::DW_FORM_ref_addr) { - assert(!useSplitDwarf() && "TODO: dwo files can't have relocations."); - // For DW_FORM_ref_addr, output the offset from beginning of debug info - // section. Origin->getOffset() returns the offset from start of the - // compile unit. - CompileUnit *CU = CUDieMap.lookup(Origin->getCompileUnit()); - assert(CU && "CUDie should belong to a CU."); - Addr += CU->getDebugInfoOffset(); - if (Asm->MAI->doesDwarfUseRelocationsAcrossSections()) - Asm->EmitLabelPlusOffset(DwarfInfoSectionSym, Addr, - DIEEntry::getRefAddrSize(Asm)); - else - Asm->EmitLabelOffsetDifference(DwarfInfoSectionSym, Addr, - DwarfInfoSectionSym, - DIEEntry::getRefAddrSize(Asm)); - } else { - // Make sure Origin belong to the same CU. - assert(Die->getCompileUnit() == Origin->getCompileUnit() && - "The referenced DIE should belong to the same CU in ref4"); - Asm->EmitInt32(Addr); - } - break; - } - case dwarf::DW_AT_ranges: { - // DW_AT_range Value encodes offset in debug_range section. - DIEInteger *V = cast<DIEInteger>(Values[i]); - - if (Asm->MAI->doesDwarfUseRelocationsAcrossSections()) { - Asm->EmitLabelPlusOffset(DwarfDebugRangeSectionSym, - V->getValue(), - 4); - } else { - Asm->EmitLabelOffsetDifference(DwarfDebugRangeSectionSym, - V->getValue(), - DwarfDebugRangeSectionSym, - 4); - } - break; - } - case dwarf::DW_AT_location: { - if (DIELabel *L = dyn_cast<DIELabel>(Values[i])) { - if (Asm->MAI->doesDwarfUseRelocationsAcrossSections()) - Asm->EmitSectionOffset(L->getValue(), DwarfDebugLocSectionSym); - else - Asm->EmitLabelDifference(L->getValue(), DwarfDebugLocSectionSym, 4); - } else { - Values[i]->EmitValue(Asm, Form); - } - break; - } - case dwarf::DW_AT_accessibility: { - if (Asm->isVerbose()) { - DIEInteger *V = cast<DIEInteger>(Values[i]); - Asm->OutStreamer.AddComment(dwarf::AccessibilityString(V->getValue())); - } - Values[i]->EmitValue(Asm, Form); - break; - } - default: - // Emit an attribute using the defined form. - Values[i]->EmitValue(Asm, Form); - break; + if (Attr == dwarf::DW_AT_accessibility) + Asm->OutStreamer.AddComment(dwarf::AccessibilityString( + cast<DIEInteger>(Values[i])->getValue())); } + + // Emit an attribute using the defined form. + Values[i]->EmitValue(Asm, Form); } // Emit the DIE children if any. - if (Abbrev->getChildrenFlag() == dwarf::DW_CHILDREN_yes) { + if (Abbrev.hasChildren()) { const std::vector<DIE *> &Children = Die->getChildren(); - for (unsigned j = 0, M = Children.size(); j < M; ++j) - emitDIE(Children[j], Abbrevs); + for (DIE *Child : Children) + emitDIE(Child); - if (Asm->isVerbose()) - Asm->OutStreamer.AddComment("End Of Children Mark"); + Asm->OutStreamer.AddComment("End Of Children Mark"); Asm->EmitInt8(0); } } // Emit the various dwarf units to the unit section USection with // the abbreviations going into ASection. -void DwarfUnits::emitUnits(DwarfDebug *DD, - const MCSection *USection, - const MCSection *ASection, - const MCSymbol *ASectionSym) { - Asm->OutStreamer.SwitchSection(USection); - for (SmallVectorImpl<CompileUnit *>::iterator I = CUs.begin(), - E = CUs.end(); I != E; ++I) { - CompileUnit *TheCU = *I; - DIE *Die = TheCU->getCUDie(); +void DwarfFile::emitUnits(DwarfDebug *DD, const MCSymbol *ASectionSym) { + for (DwarfUnit *TheU : CUs) { + DIE *Die = TheU->getUnitDie(); + const MCSection *USection = TheU->getSection(); + Asm->OutStreamer.SwitchSection(USection); // Emit the compile units header. - Asm->OutStreamer - .EmitLabel(Asm->GetTempSymbol(USection->getLabelBeginName(), - TheCU->getUniqueID())); + Asm->OutStreamer.EmitLabel(TheU->getLabelBegin()); // Emit size of content not including length itself Asm->OutStreamer.AddComment("Length of Unit"); - Asm->EmitInt32(TheCU->getHeaderSize() + Die->getSize()); + Asm->EmitInt32(TheU->getHeaderSize() + Die->getSize()); - TheCU->emitHeader(ASection, ASectionSym); + TheU->emitHeader(ASectionSym); - DD->emitDIE(Die, Abbreviations); - Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol(USection->getLabelEndName(), - TheCU->getUniqueID())); + DD->emitDIE(Die); + Asm->OutStreamer.EmitLabel(TheU->getLabelEnd()); } } // Emit the debug info section. void DwarfDebug::emitDebugInfo() { - DwarfUnits &Holder = useSplitDwarf() ? SkeletonHolder : InfoHolder; + DwarfFile &Holder = useSplitDwarf() ? SkeletonHolder : InfoHolder; - Holder.emitUnits(this, Asm->getObjFileLowering().getDwarfInfoSection(), - Asm->getObjFileLowering().getDwarfAbbrevSection(), - DwarfAbbrevSectionSym); + Holder.emitUnits(this, DwarfAbbrevSectionSym); } // Emit the abbreviation section. void DwarfDebug::emitAbbreviations() { - if (!useSplitDwarf()) - emitAbbrevs(Asm->getObjFileLowering().getDwarfAbbrevSection(), - &Abbreviations); - else - emitSkeletonAbbrevs(Asm->getObjFileLowering().getDwarfAbbrevSection()); + DwarfFile &Holder = useSplitDwarf() ? SkeletonHolder : InfoHolder; + + Holder.emitAbbrevs(Asm->getObjFileLowering().getDwarfAbbrevSection()); } -void DwarfDebug::emitAbbrevs(const MCSection *Section, - std::vector<DIEAbbrev *> *Abbrevs) { +void DwarfFile::emitAbbrevs(const MCSection *Section) { // Check to see if it is worth the effort. - if (!Abbrevs->empty()) { + if (!Abbreviations.empty()) { // Start the debug abbrev section. Asm->OutStreamer.SwitchSection(Section); - MCSymbol *Begin = Asm->GetTempSymbol(Section->getLabelBeginName()); - Asm->OutStreamer.EmitLabel(Begin); - // For each abbrevation. - for (unsigned i = 0, N = Abbrevs->size(); i < N; ++i) { - // Get abbreviation data - const DIEAbbrev *Abbrev = Abbrevs->at(i); - + for (const DIEAbbrev *Abbrev : Abbreviations) { // Emit the abbrevations code (base 1 index.) Asm->EmitULEB128(Abbrev->getNumber(), "Abbreviation Code"); @@ -2222,9 +2003,6 @@ void DwarfDebug::emitAbbrevs(const MCSection *Section, // Mark end of abbreviations. Asm->EmitULEB128(0, "EOM(3)"); - - MCSymbol *End = Asm->GetTempSymbol(Section->getLabelEndName()); - Asm->OutStreamer.EmitLabel(End); } } @@ -2241,8 +2019,9 @@ void DwarfDebug::emitEndOfLineMatrix(unsigned SectionEnd) { Asm->OutStreamer.AddComment("Section end label"); - Asm->OutStreamer.EmitSymbolValue(Asm->GetTempSymbol("section_end",SectionEnd), - Asm->getDataLayout().getPointerSize()); + Asm->OutStreamer.EmitSymbolValue( + Asm->GetTempSymbol("section_end", SectionEnd), + Asm->getDataLayout().getPointerSize()); // Mark end of matrix. Asm->OutStreamer.AddComment("DW_LNE_end_sequence"); @@ -2253,25 +2032,19 @@ void DwarfDebug::emitEndOfLineMatrix(unsigned SectionEnd) { // Emit visible names into a hashed accelerator table section. void DwarfDebug::emitAccelNames() { - DwarfAccelTable AT(DwarfAccelTable::Atom(dwarf::DW_ATOM_die_offset, - dwarf::DW_FORM_data4)); - for (DenseMap<const MDNode *, CompileUnit *>::iterator I = CUMap.begin(), - E = CUMap.end(); I != E; ++I) { - CompileUnit *TheCU = I->second; - const StringMap<std::vector<DIE*> > &Names = TheCU->getAccelNames(); - for (StringMap<std::vector<DIE*> >::const_iterator - GI = Names.begin(), GE = Names.end(); GI != GE; ++GI) { - StringRef Name = GI->getKey(); - const std::vector<DIE *> &Entities = GI->second; - for (std::vector<DIE *>::const_iterator DI = Entities.begin(), - DE = Entities.end(); DI != DE; ++DI) - AT.AddName(Name, (*DI)); + DwarfAccelTable AT( + DwarfAccelTable::Atom(dwarf::DW_ATOM_die_offset, dwarf::DW_FORM_data4)); + for (DwarfUnit *TheU : getUnits()) { + for (const auto &GI : TheU->getAccelNames()) { + StringRef Name = GI.getKey(); + for (const DIE *D : GI.second) + AT.AddName(Name, D); } } AT.FinalizeTable(Asm, "Names"); Asm->OutStreamer.SwitchSection( - Asm->getObjFileLowering().getDwarfAccelNamesSection()); + Asm->getObjFileLowering().getDwarfAccelNamesSection()); MCSymbol *SectionBegin = Asm->GetTempSymbol("names_begin"); Asm->OutStreamer.EmitLabel(SectionBegin); @@ -2282,25 +2055,19 @@ void DwarfDebug::emitAccelNames() { // Emit objective C classes and categories into a hashed accelerator table // section. void DwarfDebug::emitAccelObjC() { - DwarfAccelTable AT(DwarfAccelTable::Atom(dwarf::DW_ATOM_die_offset, - dwarf::DW_FORM_data4)); - for (DenseMap<const MDNode *, CompileUnit *>::iterator I = CUMap.begin(), - E = CUMap.end(); I != E; ++I) { - CompileUnit *TheCU = I->second; - const StringMap<std::vector<DIE*> > &Names = TheCU->getAccelObjC(); - for (StringMap<std::vector<DIE*> >::const_iterator - GI = Names.begin(), GE = Names.end(); GI != GE; ++GI) { - StringRef Name = GI->getKey(); - const std::vector<DIE *> &Entities = GI->second; - for (std::vector<DIE *>::const_iterator DI = Entities.begin(), - DE = Entities.end(); DI != DE; ++DI) - AT.AddName(Name, (*DI)); + DwarfAccelTable AT( + DwarfAccelTable::Atom(dwarf::DW_ATOM_die_offset, dwarf::DW_FORM_data4)); + for (DwarfUnit *TheU : getUnits()) { + for (const auto &GI : TheU->getAccelObjC()) { + StringRef Name = GI.getKey(); + for (const DIE *D : GI.second) + AT.AddName(Name, D); } } AT.FinalizeTable(Asm, "ObjC"); - Asm->OutStreamer.SwitchSection(Asm->getObjFileLowering() - .getDwarfAccelObjCSection()); + Asm->OutStreamer.SwitchSection( + Asm->getObjFileLowering().getDwarfAccelObjCSection()); MCSymbol *SectionBegin = Asm->GetTempSymbol("objc_begin"); Asm->OutStreamer.EmitLabel(SectionBegin); @@ -2310,25 +2077,19 @@ void DwarfDebug::emitAccelObjC() { // Emit namespace dies into a hashed accelerator table. void DwarfDebug::emitAccelNamespaces() { - DwarfAccelTable AT(DwarfAccelTable::Atom(dwarf::DW_ATOM_die_offset, - dwarf::DW_FORM_data4)); - for (DenseMap<const MDNode *, CompileUnit *>::iterator I = CUMap.begin(), - E = CUMap.end(); I != E; ++I) { - CompileUnit *TheCU = I->second; - const StringMap<std::vector<DIE*> > &Names = TheCU->getAccelNamespace(); - for (StringMap<std::vector<DIE*> >::const_iterator - GI = Names.begin(), GE = Names.end(); GI != GE; ++GI) { - StringRef Name = GI->getKey(); - const std::vector<DIE *> &Entities = GI->second; - for (std::vector<DIE *>::const_iterator DI = Entities.begin(), - DE = Entities.end(); DI != DE; ++DI) - AT.AddName(Name, (*DI)); + DwarfAccelTable AT( + DwarfAccelTable::Atom(dwarf::DW_ATOM_die_offset, dwarf::DW_FORM_data4)); + for (DwarfUnit *TheU : getUnits()) { + for (const auto &GI : TheU->getAccelNamespace()) { + StringRef Name = GI.getKey(); + for (const DIE *D : GI.second) + AT.AddName(Name, D); } } AT.FinalizeTable(Asm, "namespac"); - Asm->OutStreamer.SwitchSection(Asm->getObjFileLowering() - .getDwarfAccelNamespaceSection()); + Asm->OutStreamer.SwitchSection( + Asm->getObjFileLowering().getDwarfAccelNamespaceSection()); MCSymbol *SectionBegin = Asm->GetTempSymbol("namespac_begin"); Asm->OutStreamer.EmitLabel(SectionBegin); @@ -2339,31 +2100,24 @@ void DwarfDebug::emitAccelNamespaces() { // Emit type dies into a hashed accelerator table. void DwarfDebug::emitAccelTypes() { std::vector<DwarfAccelTable::Atom> Atoms; - Atoms.push_back(DwarfAccelTable::Atom(dwarf::DW_ATOM_die_offset, - dwarf::DW_FORM_data4)); - Atoms.push_back(DwarfAccelTable::Atom(dwarf::DW_ATOM_die_tag, - dwarf::DW_FORM_data2)); - Atoms.push_back(DwarfAccelTable::Atom(dwarf::DW_ATOM_type_flags, - dwarf::DW_FORM_data1)); + Atoms.push_back( + DwarfAccelTable::Atom(dwarf::DW_ATOM_die_offset, dwarf::DW_FORM_data4)); + Atoms.push_back( + DwarfAccelTable::Atom(dwarf::DW_ATOM_die_tag, dwarf::DW_FORM_data2)); + Atoms.push_back( + DwarfAccelTable::Atom(dwarf::DW_ATOM_type_flags, dwarf::DW_FORM_data1)); DwarfAccelTable AT(Atoms); - for (DenseMap<const MDNode *, CompileUnit *>::iterator I = CUMap.begin(), - E = CUMap.end(); I != E; ++I) { - CompileUnit *TheCU = I->second; - const StringMap<std::vector<std::pair<DIE*, unsigned > > > &Names - = TheCU->getAccelTypes(); - for (StringMap<std::vector<std::pair<DIE*, unsigned> > >::const_iterator - GI = Names.begin(), GE = Names.end(); GI != GE; ++GI) { - StringRef Name = GI->getKey(); - const std::vector<std::pair<DIE *, unsigned> > &Entities = GI->second; - for (std::vector<std::pair<DIE *, unsigned> >::const_iterator DI - = Entities.begin(), DE = Entities.end(); DI !=DE; ++DI) - AT.AddName(Name, (*DI).first, (*DI).second); + for (DwarfUnit *TheU : getUnits()) { + for (const auto &GI : TheU->getAccelTypes()) { + StringRef Name = GI.getKey(); + for (const auto &DI : GI.second) + AT.AddName(Name, DI.first, DI.second); } } AT.FinalizeTable(Asm, "types"); - Asm->OutStreamer.SwitchSection(Asm->getObjFileLowering() - .getDwarfAccelTypesSection()); + Asm->OutStreamer.SwitchSection( + Asm->getObjFileLowering().getDwarfAccelTypesSection()); MCSymbol *SectionBegin = Asm->GetTempSymbol("types_begin"); Asm->OutStreamer.EmitLabel(SectionBegin); @@ -2386,8 +2140,8 @@ void DwarfDebug::emitAccelTypes() { // reference in the pubname header doesn't change. /// computeIndexValue - Compute the gdb index value for the DIE and CU. -static dwarf::PubIndexEntryDescriptor computeIndexValue(CompileUnit *CU, - DIE *Die) { +static dwarf::PubIndexEntryDescriptor computeIndexValue(DwarfUnit *CU, + const DIE *Die) { dwarf::GDBIndexEntryLinkage Linkage = dwarf::GIEL_STATIC; // We could have a specification DIE that has our most of our knowledge, @@ -2431,176 +2185,109 @@ static dwarf::PubIndexEntryDescriptor computeIndexValue(CompileUnit *CU, /// emitDebugPubNames - Emit visible names into a debug pubnames section. /// void DwarfDebug::emitDebugPubNames(bool GnuStyle) { - const MCSection *ISec = Asm->getObjFileLowering().getDwarfInfoSection(); const MCSection *PSec = GnuStyle ? Asm->getObjFileLowering().getDwarfGnuPubNamesSection() : Asm->getObjFileLowering().getDwarfPubNamesSection(); - typedef DenseMap<const MDNode*, CompileUnit*> CUMapType; - for (CUMapType::iterator I = CUMap.begin(), E = CUMap.end(); I != E; ++I) { - CompileUnit *TheCU = I->second; - unsigned ID = TheCU->getUniqueID(); + emitDebugPubSection(GnuStyle, PSec, "Names", &DwarfUnit::getGlobalNames); +} + +void DwarfDebug::emitDebugPubSection( + bool GnuStyle, const MCSection *PSec, StringRef Name, + const StringMap<const DIE *> &(DwarfUnit::*Accessor)() const) { + for (const auto &NU : CUMap) { + DwarfCompileUnit *TheU = NU.second; + + const auto &Globals = (TheU->*Accessor)(); + + if (Globals.empty()) + continue; + + if (auto Skeleton = static_cast<DwarfCompileUnit *>(TheU->getSkeleton())) + TheU = Skeleton; + unsigned ID = TheU->getUniqueID(); // Start the dwarf pubnames section. Asm->OutStreamer.SwitchSection(PSec); - // Emit a label so we can reference the beginning of this pubname section. - if (GnuStyle) - Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("gnu_pubnames", - TheCU->getUniqueID())); - // Emit the header. - Asm->OutStreamer.AddComment("Length of Public Names Info"); - Asm->EmitLabelDifference(Asm->GetTempSymbol("pubnames_end", ID), - Asm->GetTempSymbol("pubnames_begin", ID), 4); + Asm->OutStreamer.AddComment("Length of Public " + Name + " Info"); + MCSymbol *BeginLabel = Asm->GetTempSymbol("pub" + Name + "_begin", ID); + MCSymbol *EndLabel = Asm->GetTempSymbol("pub" + Name + "_end", ID); + Asm->EmitLabelDifference(EndLabel, BeginLabel, 4); - Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("pubnames_begin", ID)); + Asm->OutStreamer.EmitLabel(BeginLabel); Asm->OutStreamer.AddComment("DWARF Version"); Asm->EmitInt16(dwarf::DW_PUBNAMES_VERSION); Asm->OutStreamer.AddComment("Offset of Compilation Unit Info"); - Asm->EmitSectionOffset(Asm->GetTempSymbol(ISec->getLabelBeginName(), ID), - DwarfInfoSectionSym); + Asm->EmitSectionOffset(TheU->getLabelBegin(), TheU->getSectionSym()); Asm->OutStreamer.AddComment("Compilation Unit Length"); - Asm->EmitLabelDifference(Asm->GetTempSymbol(ISec->getLabelEndName(), ID), - Asm->GetTempSymbol(ISec->getLabelBeginName(), ID), - 4); + Asm->EmitLabelDifference(TheU->getLabelEnd(), TheU->getLabelBegin(), 4); // Emit the pubnames for this compilation unit. - const StringMap<DIE*> &Globals = TheCU->getGlobalNames(); - for (StringMap<DIE*>::const_iterator - GI = Globals.begin(), GE = Globals.end(); GI != GE; ++GI) { - const char *Name = GI->getKeyData(); - DIE *Entity = GI->second; + for (const auto &GI : Globals) { + const char *Name = GI.getKeyData(); + const DIE *Entity = GI.second; Asm->OutStreamer.AddComment("DIE offset"); Asm->EmitInt32(Entity->getOffset()); if (GnuStyle) { - dwarf::PubIndexEntryDescriptor Desc = computeIndexValue(TheCU, Entity); + dwarf::PubIndexEntryDescriptor Desc = computeIndexValue(TheU, Entity); Asm->OutStreamer.AddComment( Twine("Kind: ") + dwarf::GDBIndexEntryKindString(Desc.Kind) + ", " + dwarf::GDBIndexEntryLinkageString(Desc.Linkage)); Asm->EmitInt8(Desc.toBits()); } - if (Asm->isVerbose()) - Asm->OutStreamer.AddComment("External Name"); - Asm->OutStreamer.EmitBytes(StringRef(Name, GI->getKeyLength()+1)); + Asm->OutStreamer.AddComment("External Name"); + Asm->OutStreamer.EmitBytes(StringRef(Name, GI.getKeyLength() + 1)); } Asm->OutStreamer.AddComment("End Mark"); Asm->EmitInt32(0); - Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("pubnames_end", ID)); + Asm->OutStreamer.EmitLabel(EndLabel); } } void DwarfDebug::emitDebugPubTypes(bool GnuStyle) { - const MCSection *ISec = Asm->getObjFileLowering().getDwarfInfoSection(); const MCSection *PSec = GnuStyle ? Asm->getObjFileLowering().getDwarfGnuPubTypesSection() : Asm->getObjFileLowering().getDwarfPubTypesSection(); - for (DenseMap<const MDNode *, CompileUnit *>::iterator I = CUMap.begin(), - E = CUMap.end(); - I != E; ++I) { - CompileUnit *TheCU = I->second; - // Start the dwarf pubtypes section. - Asm->OutStreamer.SwitchSection(PSec); - - // Emit a label so we can reference the beginning of this pubtype section. - if (GnuStyle) - Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("gnu_pubtypes", - TheCU->getUniqueID())); - - // Emit the header. - Asm->OutStreamer.AddComment("Length of Public Types Info"); - Asm->EmitLabelDifference( - Asm->GetTempSymbol("pubtypes_end", TheCU->getUniqueID()), - Asm->GetTempSymbol("pubtypes_begin", TheCU->getUniqueID()), 4); - - Asm->OutStreamer.EmitLabel( - Asm->GetTempSymbol("pubtypes_begin", TheCU->getUniqueID())); - - if (Asm->isVerbose()) - Asm->OutStreamer.AddComment("DWARF Version"); - Asm->EmitInt16(dwarf::DW_PUBTYPES_VERSION); - - Asm->OutStreamer.AddComment("Offset of Compilation Unit Info"); - Asm->EmitSectionOffset( - Asm->GetTempSymbol(ISec->getLabelBeginName(), TheCU->getUniqueID()), - DwarfInfoSectionSym); - - Asm->OutStreamer.AddComment("Compilation Unit Length"); - Asm->EmitLabelDifference( - Asm->GetTempSymbol(ISec->getLabelEndName(), TheCU->getUniqueID()), - Asm->GetTempSymbol(ISec->getLabelBeginName(), TheCU->getUniqueID()), 4); - - // Emit the pubtypes. - const StringMap<DIE *> &Globals = TheCU->getGlobalTypes(); - for (StringMap<DIE *>::const_iterator GI = Globals.begin(), - GE = Globals.end(); - GI != GE; ++GI) { - const char *Name = GI->getKeyData(); - DIE *Entity = GI->second; - - if (Asm->isVerbose()) - Asm->OutStreamer.AddComment("DIE offset"); - Asm->EmitInt32(Entity->getOffset()); - - if (GnuStyle) { - dwarf::PubIndexEntryDescriptor Desc = computeIndexValue(TheCU, Entity); - Asm->OutStreamer.AddComment( - Twine("Kind: ") + dwarf::GDBIndexEntryKindString(Desc.Kind) + ", " + - dwarf::GDBIndexEntryLinkageString(Desc.Linkage)); - Asm->EmitInt8(Desc.toBits()); - } - - if (Asm->isVerbose()) - Asm->OutStreamer.AddComment("External Name"); - - // Emit the name with a terminating null byte. - Asm->OutStreamer.EmitBytes(StringRef(Name, GI->getKeyLength() + 1)); - } - - Asm->OutStreamer.AddComment("End Mark"); - Asm->EmitInt32(0); - Asm->OutStreamer.EmitLabel( - Asm->GetTempSymbol("pubtypes_end", TheCU->getUniqueID())); - } + emitDebugPubSection(GnuStyle, PSec, "Types", &DwarfUnit::getGlobalTypes); } // Emit strings into a string section. -void DwarfUnits::emitStrings(const MCSection *StrSection, - const MCSection *OffsetSection = NULL, - const MCSymbol *StrSecSym = NULL) { +void DwarfFile::emitStrings(const MCSection *StrSection, + const MCSection *OffsetSection = NULL, + const MCSymbol *StrSecSym = NULL) { - if (StringPool.empty()) return; + if (StringPool.empty()) + return; // Start the dwarf str section. Asm->OutStreamer.SwitchSection(StrSection); // Get all of the string pool entries and put them in an array by their ID so // we can sort them. - SmallVector<std::pair<unsigned, - StringMapEntry<std::pair<MCSymbol*, unsigned> >*>, 64> Entries; + SmallVector<std::pair<unsigned, const StrPool::value_type *>, 64 > Entries; - for (StringMap<std::pair<MCSymbol*, unsigned> >::iterator - I = StringPool.begin(), E = StringPool.end(); - I != E; ++I) - Entries.push_back(std::make_pair(I->second.second, &*I)); + for (const auto &I : StringPool) + Entries.push_back(std::make_pair(I.second.second, &I)); array_pod_sort(Entries.begin(), Entries.end()); - for (unsigned i = 0, e = Entries.size(); i != e; ++i) { + for (const auto &Entry : Entries) { // Emit a label for reference from debug information entries. - Asm->OutStreamer.EmitLabel(Entries[i].second->getValue().first); + Asm->OutStreamer.EmitLabel(Entry.second->getValue().first); // Emit the string itself with a terminating null byte. - Asm->OutStreamer.EmitBytes(StringRef(Entries[i].second->getKeyData(), - Entries[i].second->getKeyLength()+1)); + Asm->OutStreamer.EmitBytes(StringRef(Entry.second->getKeyData(), + Entry.second->getKeyLength() + 1)); } // If we've got an offset section go ahead and emit that now as well. @@ -2608,17 +2295,18 @@ void DwarfUnits::emitStrings(const MCSection *StrSection, Asm->OutStreamer.SwitchSection(OffsetSection); unsigned offset = 0; unsigned size = 4; // FIXME: DWARF64 is 8. - for (unsigned i = 0, e = Entries.size(); i != e; ++i) { + for (const auto &Entry : Entries) { Asm->OutStreamer.EmitIntValue(offset, size); - offset += Entries[i].second->getKeyLength() + 1; + offset += Entry.second->getKeyLength() + 1; } } } -// Emit strings into a string section. -void DwarfUnits::emitAddresses(const MCSection *AddrSection) { +// Emit addresses into the section given. +void DwarfFile::emitAddresses(const MCSection *AddrSection) { - if (AddressPool.empty()) return; + if (AddressPool.empty()) + return; // Start the dwarf addr section. Asm->OutStreamer.SwitchSection(AddrSection); @@ -2626,147 +2314,143 @@ void DwarfUnits::emitAddresses(const MCSection *AddrSection) { // Order the address pool entries by ID SmallVector<const MCExpr *, 64> Entries(AddressPool.size()); - for (DenseMap<const MCExpr *, unsigned>::iterator I = AddressPool.begin(), - E = AddressPool.end(); - I != E; ++I) - Entries[I->second] = I->first; - - for (unsigned i = 0, e = Entries.size(); i != e; ++i) { - // Emit an expression for reference from debug information entries. - if (const MCExpr *Expr = Entries[i]) - Asm->OutStreamer.EmitValue(Expr, Asm->getDataLayout().getPointerSize()); - else - Asm->OutStreamer.EmitIntValue(0, Asm->getDataLayout().getPointerSize()); - } + for (const auto &I : AddressPool) + Entries[I.second.Number] = + I.second.TLS + ? Asm->getObjFileLowering().getDebugThreadLocalSymbol(I.first) + : MCSymbolRefExpr::Create(I.first, Asm->OutContext); + for (const MCExpr *Entry : Entries) + Asm->OutStreamer.EmitValue(Entry, Asm->getDataLayout().getPointerSize()); } // Emit visible names into a debug str section. void DwarfDebug::emitDebugStr() { - DwarfUnits &Holder = useSplitDwarf() ? SkeletonHolder : InfoHolder; + DwarfFile &Holder = useSplitDwarf() ? SkeletonHolder : InfoHolder; Holder.emitStrings(Asm->getObjFileLowering().getDwarfStrSection()); } -// Emit locations into the debug loc section. -void DwarfDebug::emitDebugLoc() { - if (DotDebugLocEntries.empty()) - return; - - for (SmallVectorImpl<DotDebugLocEntry>::iterator - I = DotDebugLocEntries.begin(), E = DotDebugLocEntries.end(); - I != E; ++I) { - DotDebugLocEntry &Entry = *I; - if (I + 1 != DotDebugLocEntries.end()) - Entry.Merge(I+1); - } - - // Start the dwarf loc section. - Asm->OutStreamer.SwitchSection( - Asm->getObjFileLowering().getDwarfLocSection()); - unsigned char Size = Asm->getDataLayout().getPointerSize(); - Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("debug_loc", 0)); - unsigned index = 1; - for (SmallVectorImpl<DotDebugLocEntry>::iterator - I = DotDebugLocEntries.begin(), E = DotDebugLocEntries.end(); - I != E; ++I, ++index) { - DotDebugLocEntry &Entry = *I; - if (Entry.isMerged()) continue; - if (Entry.isEmpty()) { - Asm->OutStreamer.EmitIntValue(0, Size); - Asm->OutStreamer.EmitIntValue(0, Size); - Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("debug_loc", index)); +void DwarfDebug::emitDebugLocEntry(ByteStreamer &Streamer, + const DebugLocEntry &Entry) { + DIVariable DV(Entry.getVariable()); + if (Entry.isInt()) { + DIBasicType BTy(resolve(DV.getType())); + if (BTy.Verify() && (BTy.getEncoding() == dwarf::DW_ATE_signed || + BTy.getEncoding() == dwarf::DW_ATE_signed_char)) { + Streamer.EmitInt8(dwarf::DW_OP_consts, "DW_OP_consts"); + Streamer.EmitSLEB128(Entry.getInt()); } else { - Asm->OutStreamer.EmitSymbolValue(Entry.getBeginSym(), Size); - Asm->OutStreamer.EmitSymbolValue(Entry.getEndSym(), Size); - DIVariable DV(Entry.getVariable()); - Asm->OutStreamer.AddComment("Loc expr size"); - MCSymbol *begin = Asm->OutStreamer.getContext().CreateTempSymbol(); - MCSymbol *end = Asm->OutStreamer.getContext().CreateTempSymbol(); - Asm->EmitLabelDifference(end, begin, 2); - Asm->OutStreamer.EmitLabel(begin); - if (Entry.isInt()) { - DIBasicType BTy(DV.getType()); - if (BTy.Verify() && - (BTy.getEncoding() == dwarf::DW_ATE_signed - || BTy.getEncoding() == dwarf::DW_ATE_signed_char)) { - Asm->OutStreamer.AddComment("DW_OP_consts"); - Asm->EmitInt8(dwarf::DW_OP_consts); - Asm->EmitSLEB128(Entry.getInt()); + Streamer.EmitInt8(dwarf::DW_OP_constu, "DW_OP_constu"); + Streamer.EmitULEB128(Entry.getInt()); + } + } else if (Entry.isLocation()) { + MachineLocation Loc = Entry.getLoc(); + if (!DV.hasComplexAddress()) + // Regular entry. + Asm->EmitDwarfRegOp(Streamer, Loc, DV.isIndirect()); + else { + // Complex address entry. + unsigned N = DV.getNumAddrElements(); + unsigned i = 0; + if (N >= 2 && DV.getAddrElement(0) == DIBuilder::OpPlus) { + if (Loc.getOffset()) { + i = 2; + Asm->EmitDwarfRegOp(Streamer, Loc, DV.isIndirect()); + Streamer.EmitInt8(dwarf::DW_OP_deref, "DW_OP_deref"); + Streamer.EmitInt8(dwarf::DW_OP_plus_uconst, "DW_OP_plus_uconst"); + Streamer.EmitSLEB128(DV.getAddrElement(1)); } else { - Asm->OutStreamer.AddComment("DW_OP_constu"); - Asm->EmitInt8(dwarf::DW_OP_constu); - Asm->EmitULEB128(Entry.getInt()); + // If first address element is OpPlus then emit + // DW_OP_breg + Offset instead of DW_OP_reg + Offset. + MachineLocation TLoc(Loc.getReg(), DV.getAddrElement(1)); + Asm->EmitDwarfRegOp(Streamer, TLoc, DV.isIndirect()); + i = 2; } - } else if (Entry.isLocation()) { - MachineLocation Loc = Entry.getLoc(); - if (!DV.hasComplexAddress()) - // Regular entry. - Asm->EmitDwarfRegOp(Loc, DV.isIndirect()); - else { - // Complex address entry. - unsigned N = DV.getNumAddrElements(); - unsigned i = 0; - if (N >= 2 && DV.getAddrElement(0) == DIBuilder::OpPlus) { - if (Loc.getOffset()) { - i = 2; - Asm->EmitDwarfRegOp(Loc, DV.isIndirect()); - Asm->OutStreamer.AddComment("DW_OP_deref"); - Asm->EmitInt8(dwarf::DW_OP_deref); - Asm->OutStreamer.AddComment("DW_OP_plus_uconst"); - Asm->EmitInt8(dwarf::DW_OP_plus_uconst); - Asm->EmitSLEB128(DV.getAddrElement(1)); - } else { - // If first address element is OpPlus then emit - // DW_OP_breg + Offset instead of DW_OP_reg + Offset. - MachineLocation TLoc(Loc.getReg(), DV.getAddrElement(1)); - Asm->EmitDwarfRegOp(TLoc, DV.isIndirect()); - i = 2; - } - } else { - Asm->EmitDwarfRegOp(Loc, DV.isIndirect()); - } + } else { + Asm->EmitDwarfRegOp(Streamer, Loc, DV.isIndirect()); + } - // Emit remaining complex address elements. - for (; i < N; ++i) { - uint64_t Element = DV.getAddrElement(i); - if (Element == DIBuilder::OpPlus) { - Asm->EmitInt8(dwarf::DW_OP_plus_uconst); - Asm->EmitULEB128(DV.getAddrElement(++i)); - } else if (Element == DIBuilder::OpDeref) { - if (!Loc.isReg()) - Asm->EmitInt8(dwarf::DW_OP_deref); - } else - llvm_unreachable("unknown Opcode found in complex address"); - } - } + // Emit remaining complex address elements. + for (; i < N; ++i) { + uint64_t Element = DV.getAddrElement(i); + if (Element == DIBuilder::OpPlus) { + Streamer.EmitInt8(dwarf::DW_OP_plus_uconst, "DW_OP_plus_uconst"); + Streamer.EmitULEB128(DV.getAddrElement(++i)); + } else if (Element == DIBuilder::OpDeref) { + if (!Loc.isReg()) + Streamer.EmitInt8(dwarf::DW_OP_deref, "DW_OP_deref"); + } else + llvm_unreachable("unknown Opcode found in complex address"); } - // else ... ignore constant fp. There is not any good way to - // to represent them here in dwarf. - Asm->OutStreamer.EmitLabel(end); } } + // else ... ignore constant fp. There is not any good way to + // to represent them here in dwarf. + // FIXME: ^ } -struct SymbolCUSorter { - SymbolCUSorter(const MCStreamer &s) : Streamer(s) {} - const MCStreamer &Streamer; +void DwarfDebug::emitDebugLocEntryLocation(const DebugLocEntry &Entry) { + Asm->OutStreamer.AddComment("Loc expr size"); + MCSymbol *begin = Asm->OutStreamer.getContext().CreateTempSymbol(); + MCSymbol *end = Asm->OutStreamer.getContext().CreateTempSymbol(); + Asm->EmitLabelDifference(end, begin, 2); + Asm->OutStreamer.EmitLabel(begin); + // Emit the entry. + APByteStreamer Streamer(*Asm); + emitDebugLocEntry(Streamer, Entry); + // Close the range. + Asm->OutStreamer.EmitLabel(end); +} - bool operator() (const SymbolCU &A, const SymbolCU &B) { - unsigned IA = A.Sym ? Streamer.GetSymbolOrder(A.Sym) : 0; - unsigned IB = B.Sym ? Streamer.GetSymbolOrder(B.Sym) : 0; +// Emit locations into the debug loc section. +void DwarfDebug::emitDebugLoc() { + // Start the dwarf loc section. + Asm->OutStreamer.SwitchSection( + Asm->getObjFileLowering().getDwarfLocSection()); + unsigned char Size = Asm->getDataLayout().getPointerSize(); + for (const auto &DebugLoc : DotDebugLocEntries) { + Asm->OutStreamer.EmitLabel(DebugLoc.Label); + for (const auto &Entry : DebugLoc.List) { + // Set up the range. This range is relative to the entry point of the + // compile unit. This is a hard coded 0 for low_pc when we're emitting + // ranges, or the DW_AT_low_pc on the compile unit otherwise. + const DwarfCompileUnit *CU = Entry.getCU(); + if (CU->getRanges().size() == 1) { + // Grab the begin symbol from the first range as our base. + const MCSymbol *Base = CU->getRanges()[0].getStart(); + Asm->EmitLabelDifference(Entry.getBeginSym(), Base, Size); + Asm->EmitLabelDifference(Entry.getEndSym(), Base, Size); + } else { + Asm->OutStreamer.EmitSymbolValue(Entry.getBeginSym(), Size); + Asm->OutStreamer.EmitSymbolValue(Entry.getEndSym(), Size); + } - // Symbols with no order assigned should be placed at the end. - // (e.g. section end labels) - if (IA == 0) - IA = (unsigned)(-1); - if (IB == 0) - IB = (unsigned)(-1); - return IA < IB; + emitDebugLocEntryLocation(Entry); + } + Asm->OutStreamer.EmitIntValue(0, Size); + Asm->OutStreamer.EmitIntValue(0, Size); } -}; +} -static bool CUSort(const CompileUnit *A, const CompileUnit *B) { - return (A->getUniqueID() < B->getUniqueID()); +void DwarfDebug::emitDebugLocDWO() { + Asm->OutStreamer.SwitchSection( + Asm->getObjFileLowering().getDwarfLocDWOSection()); + for (const auto &DebugLoc : DotDebugLocEntries) { + Asm->OutStreamer.EmitLabel(DebugLoc.Label); + for (const auto &Entry : DebugLoc.List) { + // Just always use start_length for now - at least that's one address + // rather than two. We could get fancier and try to, say, reuse an + // address we know we've emitted elsewhere (the start of the function? + // The start of the CU or CU subrange that encloses this range?) + Asm->EmitInt8(dwarf::DW_LLE_start_length_entry); + unsigned idx = InfoHolder.getAddrPoolIndex(Entry.getBeginSym()); + Asm->EmitULEB128(idx); + Asm->EmitLabelDifference(Entry.getEndSym(), Entry.getBeginSym(), 4); + + emitDebugLocEntryLocation(Entry); + } + Asm->EmitInt8(dwarf::DW_LLE_end_of_list_entry); + } } struct ArangeSpan { @@ -2777,18 +2461,17 @@ struct ArangeSpan { // address we can tie back to a CU. void DwarfDebug::emitDebugARanges() { // Start the dwarf aranges section. - Asm->OutStreamer - .SwitchSection(Asm->getObjFileLowering().getDwarfARangesSection()); + Asm->OutStreamer.SwitchSection( + Asm->getObjFileLowering().getDwarfARangesSection()); - typedef DenseMap<CompileUnit *, std::vector<ArangeSpan> > SpansType; + typedef DenseMap<DwarfCompileUnit *, std::vector<ArangeSpan> > SpansType; SpansType Spans; // Build a list of sections used. std::vector<const MCSection *> Sections; - for (SectionMapType::iterator it = SectionMap.begin(); it != SectionMap.end(); - it++) { - const MCSection *Section = it->first; + for (const auto &it : SectionMap) { + const MCSection *Section = it.first; Sections.push_back(Section); } @@ -2797,22 +2480,30 @@ void DwarfDebug::emitDebugARanges() { std::sort(Sections.begin(), Sections.end(), SectionSort); // Build a set of address spans, sorted by CU. - for (size_t SecIdx=0;SecIdx<Sections.size();SecIdx++) { - const MCSection *Section = Sections[SecIdx]; + for (const MCSection *Section : Sections) { SmallVector<SymbolCU, 8> &List = SectionMap[Section]; if (List.size() < 2) continue; // Sort the symbols by offset within the section. - SymbolCUSorter sorter(Asm->OutStreamer); - std::sort(List.begin(), List.end(), sorter); + std::sort(List.begin(), List.end(), + [&](const SymbolCU &A, const SymbolCU &B) { + unsigned IA = A.Sym ? Asm->OutStreamer.GetSymbolOrder(A.Sym) : 0; + unsigned IB = B.Sym ? Asm->OutStreamer.GetSymbolOrder(B.Sym) : 0; + + // Symbols with no order assigned should be placed at the end. + // (e.g. section end labels) + if (IA == 0) + return false; + if (IB == 0) + return true; + return IA < IB; + }); // If we have no section (e.g. common), just write out // individual spans for each symbol. if (Section == NULL) { - for (size_t n = 0; n < List.size(); n++) { - const SymbolCU &Cur = List[n]; - + for (const SymbolCU &Cur : List) { ArangeSpan Span; Span.Start = Cur.Sym; Span.End = NULL; @@ -2822,7 +2513,7 @@ void DwarfDebug::emitDebugARanges() { } else { // Build spans between each label. const MCSymbol *StartSym = List[0].Sym; - for (size_t n = 1; n < List.size(); n++) { + for (size_t n = 1, e = List.size(); n < e; n++) { const SymbolCU &Prev = List[n - 1]; const SymbolCU &Cur = List[n]; @@ -2838,37 +2529,36 @@ void DwarfDebug::emitDebugARanges() { } } - const MCSection *ISec = Asm->getObjFileLowering().getDwarfInfoSection(); unsigned PtrSize = Asm->getDataLayout().getPointerSize(); // Build a list of CUs used. - std::vector<CompileUnit *> CUs; - for (SpansType::iterator it = Spans.begin(); it != Spans.end(); it++) { - CompileUnit *CU = it->first; + std::vector<DwarfCompileUnit *> CUs; + for (const auto &it : Spans) { + DwarfCompileUnit *CU = it.first; CUs.push_back(CU); } // Sort the CU list (again, to ensure consistent output order). - std::sort(CUs.begin(), CUs.end(), CUSort); + std::sort(CUs.begin(), CUs.end(), [](const DwarfUnit *A, const DwarfUnit *B) { + return A->getUniqueID() < B->getUniqueID(); + }); // Emit an arange table for each CU we used. - for (size_t CUIdx=0;CUIdx<CUs.size();CUIdx++) { - CompileUnit *CU = CUs[CUIdx]; + for (DwarfCompileUnit *CU : CUs) { std::vector<ArangeSpan> &List = Spans[CU]; // Emit size of content not including length itself. - unsigned ContentSize - = sizeof(int16_t) // DWARF ARange version number - + sizeof(int32_t) // Offset of CU in the .debug_info section - + sizeof(int8_t) // Pointer Size (in bytes) - + sizeof(int8_t); // Segment Size (in bytes) + unsigned ContentSize = + sizeof(int16_t) + // DWARF ARange version number + sizeof(int32_t) + // Offset of CU in the .debug_info section + sizeof(int8_t) + // Pointer Size (in bytes) + sizeof(int8_t); // Segment Size (in bytes) unsigned TupleSize = PtrSize * 2; // 7.20 in the Dwarf specs requires the table to be aligned to a tuple. - unsigned Padding = 0; - while (((sizeof(int32_t) + ContentSize + Padding) % TupleSize) != 0) - Padding++; + unsigned Padding = + OffsetToAlignment(sizeof(int32_t) + ContentSize, TupleSize); ContentSize += Padding; ContentSize += (List.size() + 1) * TupleSize; @@ -2879,19 +2569,15 @@ void DwarfDebug::emitDebugARanges() { Asm->OutStreamer.AddComment("DWARF Arange version number"); Asm->EmitInt16(dwarf::DW_ARANGES_VERSION); Asm->OutStreamer.AddComment("Offset Into Debug Info Section"); - Asm->EmitSectionOffset( - Asm->GetTempSymbol(ISec->getLabelBeginName(), CU->getUniqueID()), - DwarfInfoSectionSym); + Asm->EmitSectionOffset(CU->getLocalLabelBegin(), CU->getLocalSectionSym()); Asm->OutStreamer.AddComment("Address Size (in bytes)"); Asm->EmitInt8(PtrSize); Asm->OutStreamer.AddComment("Segment Size (in bytes)"); Asm->EmitInt8(0); - for (unsigned n = 0; n < Padding; n++) - Asm->EmitInt8(0xff); + Asm->OutStreamer.EmitFill(Padding, 0xff); - for (unsigned n = 0; n < List.size(); n++) { - const ArangeSpan &Span = List[n]; + for (const ArangeSpan &Span : List) { Asm->EmitLabelReference(Span.Start, PtrSize); // Calculate the size as being from the span start to it's end. @@ -2917,122 +2603,129 @@ void DwarfDebug::emitDebugARanges() { // Emit visible names into a debug ranges section. void DwarfDebug::emitDebugRanges() { // Start the dwarf ranges section. - Asm->OutStreamer - .SwitchSection(Asm->getObjFileLowering().getDwarfRangesSection()); + Asm->OutStreamer.SwitchSection( + Asm->getObjFileLowering().getDwarfRangesSection()); + + // Size for our labels. unsigned char Size = Asm->getDataLayout().getPointerSize(); - for (SmallVectorImpl<const MCSymbol *>::iterator - I = DebugRangeSymbols.begin(), E = DebugRangeSymbols.end(); - I != E; ++I) { - if (*I) - Asm->OutStreamer.EmitSymbolValue(const_cast<MCSymbol*>(*I), Size); - else + + // Grab the specific ranges for the compile units in the module. + for (const auto &I : CUMap) { + DwarfCompileUnit *TheCU = I.second; + + // Emit a symbol so we can find the beginning of our ranges. + Asm->OutStreamer.EmitLabel(TheCU->getLabelRange()); + + // Iterate over the misc ranges for the compile units in the module. + for (const RangeSpanList &List : TheCU->getRangeLists()) { + // Emit our symbol so we can find the beginning of the range. + Asm->OutStreamer.EmitLabel(List.getSym()); + + for (const RangeSpan &Range : List.getRanges()) { + const MCSymbol *Begin = Range.getStart(); + const MCSymbol *End = Range.getEnd(); + assert(Begin && "Range without a begin symbol?"); + assert(End && "Range without an end symbol?"); + Asm->OutStreamer.EmitSymbolValue(Begin, Size); + Asm->OutStreamer.EmitSymbolValue(End, Size); + } + + // And terminate the list with two 0 values. Asm->OutStreamer.EmitIntValue(0, Size); - } -} + Asm->OutStreamer.EmitIntValue(0, Size); + } -// Emit visible names into a debug macinfo section. -void DwarfDebug::emitDebugMacInfo() { - if (const MCSection *LineInfo = - Asm->getObjFileLowering().getDwarfMacroInfoSection()) { - // Start the dwarf macinfo section. - Asm->OutStreamer.SwitchSection(LineInfo); + // Now emit a range for the CU itself. + if (TheCU->getRanges().size() > 1) { + Asm->OutStreamer.EmitLabel( + Asm->GetTempSymbol("cu_ranges", TheCU->getUniqueID())); + for (const RangeSpan &Range : TheCU->getRanges()) { + const MCSymbol *Begin = Range.getStart(); + const MCSymbol *End = Range.getEnd(); + assert(Begin && "Range without a begin symbol?"); + assert(End && "Range without an end symbol?"); + Asm->OutStreamer.EmitSymbolValue(Begin, Size); + Asm->OutStreamer.EmitSymbolValue(End, Size); + } + // And terminate the list with two 0 values. + Asm->OutStreamer.EmitIntValue(0, Size); + Asm->OutStreamer.EmitIntValue(0, Size); + } } } // DWARF5 Experimental Separate Dwarf emitters. -// This DIE has the following attributes: DW_AT_comp_dir, DW_AT_stmt_list, -// DW_AT_low_pc, DW_AT_high_pc, DW_AT_ranges, DW_AT_dwo_name, DW_AT_dwo_id, -// DW_AT_ranges_base, DW_AT_addr_base. -CompileUnit *DwarfDebug::constructSkeletonCU(const CompileUnit *CU) { +void DwarfDebug::initSkeletonUnit(const DwarfUnit *U, DIE *Die, + DwarfUnit *NewU) { + NewU->addLocalString(Die, dwarf::DW_AT_GNU_dwo_name, + U->getCUNode().getSplitDebugFilename()); - DIE *Die = new DIE(dwarf::DW_TAG_compile_unit); - CompileUnit *NewCU = new CompileUnit(CU->getUniqueID(), Die, CU->getNode(), - Asm, this, &SkeletonHolder); - - NewCU->addLocalString(Die, dwarf::DW_AT_GNU_dwo_name, - CU->getNode().getSplitDebugFilename()); - - // Relocate to the beginning of the addr_base section, else 0 for the - // beginning of the one for this compile unit. - if (Asm->MAI->doesDwarfUseRelocationsAcrossSections()) - NewCU->addLabel(Die, dwarf::DW_AT_GNU_addr_base, dwarf::DW_FORM_sec_offset, - DwarfAddrSectionSym); - else - NewCU->addUInt(Die, dwarf::DW_AT_GNU_addr_base, - dwarf::DW_FORM_sec_offset, 0); + if (!CompilationDir.empty()) + NewU->addLocalString(Die, dwarf::DW_AT_comp_dir, CompilationDir); - // 2.17.1 requires that we use DW_AT_low_pc for a single entry point - // into an entity. We're using 0, or a NULL label for this. - NewCU->addUInt(Die, dwarf::DW_AT_low_pc, dwarf::DW_FORM_addr, 0); + addGnuPubAttributes(NewU, Die); - // DW_AT_stmt_list is a offset of line number information for this - // compile unit in debug_line section. - // FIXME: Should handle multiple compile units. - if (Asm->MAI->doesDwarfUseRelocationsAcrossSections()) - NewCU->addLabel(Die, dwarf::DW_AT_stmt_list, dwarf::DW_FORM_sec_offset, - DwarfLineSectionSym); - else - NewCU->addUInt(Die, dwarf::DW_AT_stmt_list, dwarf::DW_FORM_sec_offset, 0); - - if (!CompilationDir.empty()) - NewCU->addLocalString(Die, dwarf::DW_AT_comp_dir, CompilationDir); + SkeletonHolder.addUnit(NewU); +} - // Flags to let the linker know we have emitted new style pubnames. - if (GenerateGnuPubSections) { - if (Asm->MAI->doesDwarfUseRelocationsAcrossSections()) - NewCU->addLabel(Die, dwarf::DW_AT_GNU_pubnames, dwarf::DW_FORM_sec_offset, - Asm->GetTempSymbol("gnu_pubnames", NewCU->getUniqueID())); - else - NewCU->addDelta(Die, dwarf::DW_AT_GNU_pubnames, dwarf::DW_FORM_data4, - Asm->GetTempSymbol("gnu_pubnames", NewCU->getUniqueID()), - DwarfGnuPubNamesSectionSym); +// This DIE has the following attributes: DW_AT_comp_dir, DW_AT_stmt_list, +// DW_AT_low_pc, DW_AT_high_pc, DW_AT_ranges, DW_AT_dwo_name, DW_AT_dwo_id, +// DW_AT_addr_base, DW_AT_ranges_base. +DwarfCompileUnit *DwarfDebug::constructSkeletonCU(const DwarfCompileUnit *CU) { - if (Asm->MAI->doesDwarfUseRelocationsAcrossSections()) - NewCU->addLabel(Die, dwarf::DW_AT_GNU_pubtypes, dwarf::DW_FORM_sec_offset, - Asm->GetTempSymbol("gnu_pubtypes", NewCU->getUniqueID())); - else - NewCU->addDelta(Die, dwarf::DW_AT_GNU_pubtypes, dwarf::DW_FORM_data4, - Asm->GetTempSymbol("gnu_pubtypes", NewCU->getUniqueID()), - DwarfGnuPubTypesSectionSym); - } + DIE *Die = new DIE(dwarf::DW_TAG_compile_unit); + DwarfCompileUnit *NewCU = new DwarfCompileUnit( + CU->getUniqueID(), Die, CU->getCUNode(), Asm, this, &SkeletonHolder); + NewCU->initSection(Asm->getObjFileLowering().getDwarfInfoSection(), + DwarfInfoSectionSym); - // Flag if we've emitted any ranges and their location for the compile unit. - if (DebugRangeSymbols.size()) { - if (Asm->MAI->doesDwarfUseRelocationsAcrossSections()) - NewCU->addLabel(Die, dwarf::DW_AT_GNU_ranges_base, - dwarf::DW_FORM_sec_offset, DwarfDebugRangeSectionSym); - else - NewCU->addUInt(Die, dwarf::DW_AT_GNU_ranges_base, dwarf::DW_FORM_data4, - 0); - } + NewCU->initStmtList(DwarfLineSectionSym); - SkeletonHolder.addUnit(NewCU); - SkeletonCUs.push_back(NewCU); + initSkeletonUnit(CU, Die, NewCU); return NewCU; } -void DwarfDebug::emitSkeletonAbbrevs(const MCSection *Section) { - assert(useSplitDwarf() && "No split dwarf debug info?"); - emitAbbrevs(Section, &SkeletonAbbrevs); +// This DIE has the following attributes: DW_AT_comp_dir, DW_AT_dwo_name, +// DW_AT_addr_base. +DwarfTypeUnit *DwarfDebug::constructSkeletonTU(DwarfTypeUnit *TU) { + DwarfCompileUnit &CU = static_cast<DwarfCompileUnit &>( + *SkeletonHolder.getUnits()[TU->getCU().getUniqueID()]); + + DIE *Die = new DIE(dwarf::DW_TAG_type_unit); + DwarfTypeUnit *NewTU = + new DwarfTypeUnit(TU->getUniqueID(), Die, CU, Asm, this, &SkeletonHolder); + NewTU->setTypeSignature(TU->getTypeSignature()); + NewTU->setType(NULL); + NewTU->initSection( + Asm->getObjFileLowering().getDwarfTypesSection(TU->getTypeSignature())); + + initSkeletonUnit(TU, Die, NewTU); + return NewTU; } // Emit the .debug_info.dwo section for separated dwarf. This contains the // compile units that would normally be in debug_info. void DwarfDebug::emitDebugInfoDWO() { assert(useSplitDwarf() && "No split dwarf debug info?"); - InfoHolder.emitUnits(this, Asm->getObjFileLowering().getDwarfInfoDWOSection(), - Asm->getObjFileLowering().getDwarfAbbrevDWOSection(), - DwarfAbbrevDWOSectionSym); + // Don't pass an abbrev symbol, using a constant zero instead so as not to + // emit relocations into the dwo file. + InfoHolder.emitUnits(this, /* AbbrevSymbol */nullptr); } // Emit the .debug_abbrev.dwo section for separated dwarf. This contains the // abbreviations for the .debug_info.dwo section. void DwarfDebug::emitDebugAbbrevDWO() { assert(useSplitDwarf() && "No split dwarf?"); - emitAbbrevs(Asm->getObjFileLowering().getDwarfAbbrevDWOSection(), - &Abbreviations); + InfoHolder.emitAbbrevs(Asm->getObjFileLowering().getDwarfAbbrevDWOSection()); +} + +void DwarfDebug::emitDebugLineDWO() { + assert(useSplitDwarf() && "No split dwarf?"); + Asm->OutStreamer.SwitchSection( + Asm->getObjFileLowering().getDwarfLineDWOSection()); + SplitTypeUnitFileTable.Emit(Asm->OutStreamer); } // Emit the .debug_str.dwo section for separated dwarf. This contains the @@ -3040,9 +2733,75 @@ void DwarfDebug::emitDebugAbbrevDWO() { // sections. void DwarfDebug::emitDebugStrDWO() { assert(useSplitDwarf() && "No split dwarf?"); - const MCSection *OffSec = Asm->getObjFileLowering() - .getDwarfStrOffDWOSection(); + const MCSection *OffSec = + Asm->getObjFileLowering().getDwarfStrOffDWOSection(); const MCSymbol *StrSym = DwarfStrSectionSym; InfoHolder.emitStrings(Asm->getObjFileLowering().getDwarfStrDWOSection(), OffSec, StrSym); } + +MCDwarfDwoLineTable *DwarfDebug::getDwoLineTable(const DwarfCompileUnit &CU) { + if (!useSplitDwarf()) + return nullptr; + if (SingleCU) + SplitTypeUnitFileTable.setCompilationDir(CU.getCUNode().getDirectory()); + return &SplitTypeUnitFileTable; +} + +void DwarfDebug::addDwarfTypeUnitType(DwarfCompileUnit &CU, + StringRef Identifier, DIE *RefDie, + DICompositeType CTy) { + // Flag the type unit reference as a declaration so that if it contains + // members (implicit special members, static data member definitions, member + // declarations for definitions in this CU, etc) consumers don't get confused + // and think this is a full definition. + CU.addFlag(RefDie, dwarf::DW_AT_declaration); + + const DwarfTypeUnit *&TU = DwarfTypeUnits[CTy]; + if (TU) { + CU.addDIETypeSignature(RefDie, *TU); + return; + } + + DIE *UnitDie = new DIE(dwarf::DW_TAG_type_unit); + DwarfTypeUnit *NewTU = + new DwarfTypeUnit(InfoHolder.getUnits().size(), UnitDie, CU, Asm, this, + &InfoHolder, getDwoLineTable(CU)); + TU = NewTU; + InfoHolder.addUnit(NewTU); + + NewTU->addUInt(UnitDie, dwarf::DW_AT_language, dwarf::DW_FORM_data2, + CU.getLanguage()); + + MD5 Hash; + Hash.update(Identifier); + // ... take the least significant 8 bytes and return those. Our MD5 + // implementation always returns its results in little endian, swap bytes + // appropriately. + MD5::MD5Result Result; + Hash.final(Result); + uint64_t Signature = *reinterpret_cast<support::ulittle64_t *>(Result + 8); + NewTU->setTypeSignature(Signature); + if (useSplitDwarf()) + NewTU->setSkeleton(constructSkeletonTU(NewTU)); + else + CU.applyStmtList(*UnitDie); + + NewTU->setType(NewTU->createTypeDIE(CTy)); + + NewTU->initSection( + useSplitDwarf() + ? Asm->getObjFileLowering().getDwarfTypesDWOSection(Signature) + : Asm->getObjFileLowering().getDwarfTypesSection(Signature)); + + CU.addDIETypeSignature(RefDie, *NewTU); +} + +void DwarfDebug::attachLowHighPC(DwarfCompileUnit *Unit, DIE *D, + MCSymbol *Begin, MCSymbol *End) { + Unit->addLabelAddress(D, dwarf::DW_AT_low_pc, Begin); + if (DwarfVersion < 4) + Unit->addLabelAddress(D, dwarf::DW_AT_high_pc, End); + else + Unit->addLabelDelta(D, dwarf::DW_AT_high_pc, End, Begin); +} diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.h b/lib/CodeGen/AsmPrinter/DwarfDebug.h index cebac39a19..da708f510c 100644 --- a/lib/CodeGen/AsmPrinter/DwarfDebug.h +++ b/lib/CodeGen/AsmPrinter/DwarfDebug.h @@ -14,44 +14,44 @@ #ifndef CODEGEN_ASMPRINTER_DWARFDEBUG_H__ #define CODEGEN_ASMPRINTER_DWARFDEBUG_H__ +#include "AsmPrinterHandler.h" #include "DIE.h" +#include "DebugLocEntry.h" +#include "DebugLocList.h" #include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/FoldingSet.h" -#include "llvm/ADT/SetVector.h" +#include "llvm/ADT/MapVector.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/StringMap.h" -#include "llvm/CodeGen/AsmPrinter.h" +#include "llvm/ADT/FoldingSet.h" #include "llvm/CodeGen/LexicalScopes.h" -#include "llvm/DebugInfo.h" +#include "llvm/IR/DebugInfo.h" +#include "llvm/IR/DebugLoc.h" #include "llvm/MC/MachineLocation.h" +#include "llvm/MC/MCDwarf.h" #include "llvm/Support/Allocator.h" -#include "llvm/Support/DebugLoc.h" namespace llvm { -class CompileUnit; +class AsmPrinter; +class ByteStreamer; class ConstantInt; class ConstantFP; -class DbgVariable; -class MachineFrameInfo; +class DwarfCompileUnit; +class DwarfDebug; +class DwarfTypeUnit; +class DwarfUnit; class MachineModuleInfo; -class MachineOperand; -class MCAsmInfo; -class DIEAbbrev; -class DIE; -class DIEBlock; -class DIEEntry; //===----------------------------------------------------------------------===// /// \brief This class is used to record source line correspondence. class SrcLineInfo { - unsigned Line; // Source line number. - unsigned Column; // Source column. - unsigned SourceID; // Source ID number. - MCSymbol *Label; // Label in code ID number. + unsigned Line; // Source line number. + unsigned Column; // Source column. + unsigned SourceID; // Source ID number. + MCSymbol *Label; // Label in code ID number. public: SrcLineInfo(unsigned L, unsigned C, unsigned S, MCSymbol *label) - : Line(L), Column(C), SourceID(S), Label(label) {} + : Line(L), Column(C), SourceID(S), Label(label) {} // Accessors unsigned getLine() const { return Line; } @@ -60,124 +60,44 @@ public: MCSymbol *getLabel() const { return Label; } }; -/// \brief This struct describes location entries emitted in the .debug_loc -/// section. -class DotDebugLocEntry { - // Begin and end symbols for the address range that this location is valid. - const MCSymbol *Begin; - const MCSymbol *End; - - // Type of entry that this represents. - enum EntryType { - E_Location, - E_Integer, - E_ConstantFP, - E_ConstantInt - }; - enum EntryType EntryKind; - - union { - int64_t Int; - const ConstantFP *CFP; - const ConstantInt *CIP; - } Constants; - - // The location in the machine frame. - MachineLocation Loc; - - // The variable to which this location entry corresponds. - const MDNode *Variable; - - // Whether this location has been merged. - bool Merged; - -public: - DotDebugLocEntry() : Begin(0), End(0), Variable(0), Merged(false) { - Constants.Int = 0; - } - DotDebugLocEntry(const MCSymbol *B, const MCSymbol *E, MachineLocation &L, - const MDNode *V) - : Begin(B), End(E), Loc(L), Variable(V), Merged(false) { - Constants.Int = 0; - EntryKind = E_Location; - } - DotDebugLocEntry(const MCSymbol *B, const MCSymbol *E, int64_t i) - : Begin(B), End(E), Variable(0), Merged(false) { - Constants.Int = i; - EntryKind = E_Integer; - } - DotDebugLocEntry(const MCSymbol *B, const MCSymbol *E, const ConstantFP *FPtr) - : Begin(B), End(E), Variable(0), Merged(false) { - Constants.CFP = FPtr; - EntryKind = E_ConstantFP; - } - DotDebugLocEntry(const MCSymbol *B, const MCSymbol *E, - const ConstantInt *IPtr) - : Begin(B), End(E), Variable(0), Merged(false) { - Constants.CIP = IPtr; - EntryKind = E_ConstantInt; - } - - /// \brief Empty entries are also used as a trigger to emit temp label. Such - /// labels are referenced is used to find debug_loc offset for a given DIE. - bool isEmpty() { return Begin == 0 && End == 0; } - bool isMerged() { return Merged; } - void Merge(DotDebugLocEntry *Next) { - if (!(Begin && Loc == Next->Loc && End == Next->Begin)) - return; - Next->Begin = Begin; - Merged = true; - } - bool isLocation() const { return EntryKind == E_Location; } - bool isInt() const { return EntryKind == E_Integer; } - bool isConstantFP() const { return EntryKind == E_ConstantFP; } - bool isConstantInt() const { return EntryKind == E_ConstantInt; } - int64_t getInt() const { return Constants.Int; } - const ConstantFP *getConstantFP() const { return Constants.CFP; } - const ConstantInt *getConstantInt() const { return Constants.CIP; } - const MDNode *getVariable() const { return Variable; } - const MCSymbol *getBeginSym() const { return Begin; } - const MCSymbol *getEndSym() const { return End; } - MachineLocation getLoc() const { return Loc; } -}; - //===----------------------------------------------------------------------===// /// \brief This class is used to track local variable information. class DbgVariable { - DIVariable Var; // Variable Descriptor. - DIE *TheDIE; // Variable DIE. - unsigned DotDebugLocOffset; // Offset in DotDebugLocEntries. - DbgVariable *AbsVar; // Corresponding Abstract variable, if any. - const MachineInstr *MInsn; // DBG_VALUE instruction of the variable. + DIVariable Var; // Variable Descriptor. + DIE *TheDIE; // Variable DIE. + unsigned DotDebugLocOffset; // Offset in DotDebugLocEntries. + DbgVariable *AbsVar; // Corresponding Abstract variable, if any. + const MachineInstr *MInsn; // DBG_VALUE instruction of the variable. int FrameIndex; DwarfDebug *DD; + public: // AbsVar may be NULL. DbgVariable(DIVariable V, DbgVariable *AV, DwarfDebug *DD) - : Var(V), TheDIE(0), DotDebugLocOffset(~0U), AbsVar(AV), MInsn(0), - FrameIndex(~0), DD(DD) {} + : Var(V), TheDIE(0), DotDebugLocOffset(~0U), AbsVar(AV), MInsn(0), + FrameIndex(~0), DD(DD) {} // Accessors. - DIVariable getVariable() const { return Var; } - void setDIE(DIE *D) { TheDIE = D; } - DIE *getDIE() const { return TheDIE; } - void setDotDebugLocOffset(unsigned O) { DotDebugLocOffset = O; } - unsigned getDotDebugLocOffset() const { return DotDebugLocOffset; } - StringRef getName() const { return Var.getName(); } + DIVariable getVariable() const { return Var; } + void setDIE(DIE *D) { TheDIE = D; } + DIE *getDIE() const { return TheDIE; } + void setDotDebugLocOffset(unsigned O) { DotDebugLocOffset = O; } + unsigned getDotDebugLocOffset() const { return DotDebugLocOffset; } + StringRef getName() const { return Var.getName(); } DbgVariable *getAbstractVariable() const { return AbsVar; } - const MachineInstr *getMInsn() const { return MInsn; } - void setMInsn(const MachineInstr *M) { MInsn = M; } - int getFrameIndex() const { return FrameIndex; } - void setFrameIndex(int FI) { FrameIndex = FI; } + const MachineInstr *getMInsn() const { return MInsn; } + void setMInsn(const MachineInstr *M) { MInsn = M; } + int getFrameIndex() const { return FrameIndex; } + void setFrameIndex(int FI) { FrameIndex = FI; } // Translate tag to proper Dwarf tag. - uint16_t getTag() const { + uint16_t getTag() const { if (Var.getTag() == dwarf::DW_TAG_arg_variable) return dwarf::DW_TAG_formal_parameter; return dwarf::DW_TAG_variable; } /// \brief Return true if DbgVariable is artificial. - bool isArtificial() const { + bool isArtificial() const { if (Var.isArtificial()) return true; if (getType().isArtificial()) @@ -185,7 +105,7 @@ public: return false; } - bool isObjectPointer() const { + bool isObjectPointer() const { if (Var.isObjectPointer()) return true; if (getType().isObjectPointer()) @@ -193,21 +113,16 @@ public: return false; } - bool variableHasComplexAddress() const { + bool variableHasComplexAddress() const { assert(Var.isVariable() && "Invalid complex DbgVariable!"); return Var.hasComplexAddress(); } - bool isBlockByrefVariable() const { - assert(Var.isVariable() && "Invalid complex DbgVariable!"); - return Var.isBlockByrefVariable(); - } - unsigned getNumAddrElements() const { + bool isBlockByrefVariable() const; + unsigned getNumAddrElements() const { assert(Var.isVariable() && "Invalid complex DbgVariable!"); return Var.getNumAddrElements(); } - uint64_t getAddrElement(unsigned i) const { - return Var.getAddrElement(i); - } + uint64_t getAddrElement(unsigned i) const { return Var.getAddrElement(i); } DIType getType() const; private: @@ -217,43 +132,50 @@ private: }; /// \brief Collects and handles information specific to a particular -/// collection of units. -class DwarfUnits { +/// collection of units. This collection represents all of the units +/// that will be ultimately output into a single object file. +class DwarfFile { // Target of Dwarf emission, used for sizing of abbreviations. AsmPrinter *Asm; // Used to uniquely define abbreviations. - FoldingSet<DIEAbbrev> *AbbreviationsSet; + FoldingSet<DIEAbbrev> AbbreviationsSet; // A list of all the unique abbreviations in use. - std::vector<DIEAbbrev *> &Abbreviations; + std::vector<DIEAbbrev *> Abbreviations; // A pointer to all units in the section. - SmallVector<CompileUnit *, 1> CUs; + SmallVector<DwarfUnit *, 1> CUs; // Collection of strings for this unit and assorted symbols. // A String->Symbol mapping of strings used by indirect // references. - typedef StringMap<std::pair<MCSymbol*, unsigned>, - BumpPtrAllocator&> StrPool; + typedef StringMap<std::pair<MCSymbol *, unsigned>, BumpPtrAllocator &> + StrPool; StrPool StringPool; unsigned NextStringPoolNumber; std::string StringPref; + struct AddressPoolEntry { + unsigned Number; + bool TLS; + AddressPoolEntry(unsigned Number, bool TLS) : Number(Number), TLS(TLS) {} + }; // Collection of addresses for this unit and assorted labels. // A Symbol->unsigned mapping of addresses used by indirect // references. - typedef DenseMap<const MCExpr *, unsigned> AddrPool; + typedef DenseMap<const MCSymbol *, AddressPoolEntry> AddrPool; AddrPool AddressPool; unsigned NextAddrPoolNumber; public: - DwarfUnits(AsmPrinter *AP, FoldingSet<DIEAbbrev> *AS, - std::vector<DIEAbbrev *> &A, const char *Pref, - BumpPtrAllocator &DA) - : Asm(AP), AbbreviationsSet(AS), Abbreviations(A), StringPool(DA), - NextStringPoolNumber(0), StringPref(Pref), AddressPool(), - NextAddrPoolNumber(0) {} + DwarfFile(AsmPrinter *AP, const char *Pref, BumpPtrAllocator &DA) + : Asm(AP), StringPool(DA), NextStringPoolNumber(0), StringPref(Pref), + AddressPool(), NextAddrPoolNumber(0) {} + + ~DwarfFile(); + + const SmallVectorImpl<DwarfUnit *> &getUnits() { return CUs; } /// \brief Compute the size and offset of a DIE given an incoming Offset. unsigned computeSizeAndOffset(DIE *Die, unsigned Offset); @@ -265,12 +187,14 @@ public: void assignAbbrevNumber(DIEAbbrev &Abbrev); /// \brief Add a unit to the list of CUs. - void addUnit(CompileUnit *CU) { CUs.push_back(CU); } + void addUnit(DwarfUnit *CU) { CUs.push_back(CU); } /// \brief Emit all of the units to the section listed with the given /// abbreviation section. - void emitUnits(DwarfDebug *DD, const MCSection *USection, - const MCSection *ASection, const MCSymbol *ASectionSym); + void emitUnits(DwarfDebug *DD, const MCSymbol *ASectionSym); + + /// \brief Emit a set of abbreviations to the specific section. + void emitAbbrevs(const MCSection *); /// \brief Emit all of the strings to the section given. void emitStrings(const MCSection *StrSection, const MCSection *OffsetSection, @@ -295,8 +219,7 @@ public: /// \brief Returns the index into the address pool with the given /// label/symbol. - unsigned getAddrPoolIndex(const MCExpr *Sym); - unsigned getAddrPoolIndex(const MCSymbol *Sym); + unsigned getAddrPoolIndex(const MCSymbol *Sym, bool TLS = false); /// \brief Returns the address pool. AddrPool *getAddrPool() { return &AddressPool; } @@ -304,13 +227,13 @@ public: /// \brief Helper used to pair up a symbol and its DWARF compile unit. struct SymbolCU { - SymbolCU(CompileUnit *CU, const MCSymbol *Sym) : Sym(Sym), CU(CU) {} + SymbolCU(DwarfCompileUnit *CU, const MCSymbol *Sym) : Sym(Sym), CU(CU) {} const MCSymbol *Sym; - CompileUnit *CU; + DwarfCompileUnit *CU; }; /// \brief Collects and handles dwarf debug information. -class DwarfDebug { +class DwarfDebug : public AsmPrinterHandler { // Target of Dwarf emission. AsmPrinter *Asm; @@ -320,40 +243,31 @@ class DwarfDebug { // All DIEValues are allocated through this allocator. BumpPtrAllocator DIEValueAllocator; - // Handle to the a compile unit used for the inline extension handling. - CompileUnit *FirstCU; + // Handle to the compile unit used for the inline extension handling, + // this is just so that the DIEValue allocator has a place to store + // the particular elements. + // FIXME: Store these off of DwarfDebug instead? + DwarfCompileUnit *FirstCU; - // Maps MDNode with its corresponding CompileUnit. - DenseMap <const MDNode *, CompileUnit *> CUMap; + // Maps MDNode with its corresponding DwarfCompileUnit. + MapVector<const MDNode *, DwarfCompileUnit *> CUMap; - // Maps subprogram MDNode with its corresponding CompileUnit. - DenseMap <const MDNode *, CompileUnit *> SPMap; + // Maps subprogram MDNode with its corresponding DwarfCompileUnit. + DenseMap<const MDNode *, DwarfCompileUnit *> SPMap; - // Maps a CU DIE with its corresponding CompileUnit. - DenseMap <const DIE *, CompileUnit *> CUDieMap; + // Maps a CU DIE with its corresponding DwarfCompileUnit. + DenseMap<const DIE *, DwarfCompileUnit *> CUDieMap; - /// Maps MDNodes for type sysstem with the corresponding DIEs. These DIEs can + /// Maps MDNodes for type system with the corresponding DIEs. These DIEs can /// be shared across CUs, that is why we keep the map here instead - /// of in CompileUnit. + /// of in DwarfCompileUnit. DenseMap<const MDNode *, DIE *> MDTypeNodeToDieMap; - // Used to uniquely define abbreviations. - FoldingSet<DIEAbbrev> AbbreviationsSet; - - // A list of all the unique abbreviations in use. - std::vector<DIEAbbrev *> Abbreviations; - - // Stores the current file ID for a given compile unit. - DenseMap <unsigned, unsigned> FileIDCUMap; - // Source id map, i.e. CUID, source filename and directory, - // separated by a zero byte, mapped to a unique id. - StringMap<unsigned, BumpPtrAllocator&> SourceIdMap; - // List of all labels used in aranges generation. std::vector<SymbolCU> ArangeLabels; // Size of each symbol emitted (for those symbols that have a specific size). - DenseMap <const MCSymbol *, uint64_t> SymSize; + DenseMap<const MCSymbol *, uint64_t> SymSize; // Provides a unique id per text section. typedef DenseMap<const MCSection *, SmallVector<SymbolCU, 8> > SectionMapType; @@ -368,15 +282,16 @@ class DwarfDebug { DenseMap<const MDNode *, DIE *> AbstractSPDies; // Collection of dbg variables of a scope. - typedef DenseMap<LexicalScope *, - SmallVector<DbgVariable *, 8> > ScopeVariablesMap; + typedef DenseMap<LexicalScope *, SmallVector<DbgVariable *, 8> > + ScopeVariablesMap; ScopeVariablesMap ScopeVariables; // Collection of abstract variables. DenseMap<const MDNode *, DbgVariable *> AbstractVariables; - // Collection of DotDebugLocEntry. - SmallVector<DotDebugLocEntry, 4> DotDebugLocEntries; + // Collection of DebugLocEntry. Stored in a linked list so that DIELocLists + // can refer to them in spite of insertions into this list. + SmallVector<DebugLocList, 4> DotDebugLocEntries; // Collection of subprogram DIEs that are marked (at the end of the module) // as DW_AT_inline. @@ -394,17 +309,15 @@ class DwarfDebug { // Every user variable mentioned by a DBG_VALUE instruction in order of // appearance. - SmallVector<const MDNode*, 8> UserVariables; + SmallVector<const MDNode *, 8> UserVariables; // For each user variable, keep a list of DBG_VALUE instructions in order. // The list can also contain normal instructions that clobber the previous // DBG_VALUE. - typedef DenseMap<const MDNode*, SmallVector<const MachineInstr*, 4> > - DbgValueHistoryMap; + typedef DenseMap<const MDNode *, SmallVector<const MachineInstr *, 4> > + DbgValueHistoryMap; DbgValueHistoryMap DbgValues; - SmallVector<const MCSymbol *, 8> DebugRangeSymbols; - // Previous instruction's location information. This is used to determine // label location to indicate scope boundries in dwarf debug info. DebugLoc PrevInstLoc; @@ -414,6 +327,19 @@ class DwarfDebug { // body. DebugLoc PrologEndLoc; + // If nonnull, stores the current machine function we're processing. + const MachineFunction *CurFn; + + // If nonnull, stores the current machine instruction we're processing. + const MachineInstr *CurMI; + + // If nonnull, stores the section that the previous function was allocated to + // emitting. + const MCSection *PrevSection; + + // If nonnull, stores the CU in which the previous subprogram was contained. + const DwarfCompileUnit *PrevCU; + // Section Symbols: these are assembler temporary labels that are emitted at // the beginning of each supported dwarf section. These are used to form // section offsets and are created by EmitSectionLabels. @@ -421,36 +347,48 @@ class DwarfDebug { MCSymbol *DwarfStrSectionSym, *TextSectionSym, *DwarfDebugRangeSectionSym; MCSymbol *DwarfDebugLocSectionSym, *DwarfLineSectionSym, *DwarfAddrSectionSym; MCSymbol *FunctionBeginSym, *FunctionEndSym; - MCSymbol *DwarfAbbrevDWOSectionSym, *DwarfStrDWOSectionSym; + MCSymbol *DwarfInfoDWOSectionSym, *DwarfAbbrevDWOSectionSym; + MCSymbol *DwarfStrDWOSectionSym; MCSymbol *DwarfGnuPubNamesSectionSym, *DwarfGnuPubTypesSectionSym; // As an optimization, there is no need to emit an entry in the directory // table for the same directory as DW_AT_comp_dir. StringRef CompilationDir; - // Counter for assigning globally unique IDs for CUs. - unsigned GlobalCUIndexCount; + // Counter for assigning globally unique IDs for ranges. + unsigned GlobalRangeCount; // Holder for the file specific debug information. - DwarfUnits InfoHolder; + DwarfFile InfoHolder; // Holders for the various debug information flags that we might need to // have exposed. See accessor functions below for description. // Holder for imported entities. typedef SmallVector<std::pair<const MDNode *, const MDNode *>, 32> - ImportedEntityMap; + ImportedEntityMap; ImportedEntityMap ScopesWithImportedEntities; - // Holder for types that are going to be extracted out into a type unit. - std::vector<DIE *> TypeUnits; + // Map from MDNodes for user-defined types to the type units that describe + // them. + DenseMap<const MDNode *, const DwarfTypeUnit *> DwarfTypeUnits; // Whether to emit the pubnames/pubtypes sections. bool HasDwarfPubSections; + // Whether or not to use AT_ranges for compilation units. + bool HasCURanges; + + // Whether we emitted a function into a section other than the default + // text. + bool UsedNonDefaultText; + // Version of dwarf we're emitting. unsigned DwarfVersion; + // Maps from a type identifier to the actual MDNode. + DITypeIdentifierMap TypeIdentifierMap; + // DWARF5 Experimental Options bool HasDwarfAccelTables; bool HasSplitDwarf; @@ -460,25 +398,27 @@ class DwarfDebug { // original object file, rather than things that are meant // to be in the .dwo sections. - // The CUs left in the original object file for separated debug info. - SmallVector<CompileUnit *, 1> SkeletonCUs; - - // Used to uniquely define abbreviations for the skeleton emission. - FoldingSet<DIEAbbrev> SkeletonAbbrevSet; - - // A list of all the unique abbreviations in use. - std::vector<DIEAbbrev *> SkeletonAbbrevs; - // Holder for the skeleton information. - DwarfUnits SkeletonHolder; + DwarfFile SkeletonHolder; - // Maps from a type identifier to the actual MDNode. - DITypeIdentifierMap TypeIdentifierMap; + /// Store file names for type units under fission in a line table header that + /// will be emitted into debug_line.dwo. + // FIXME: replace this with a map from comp_dir to table so that we can emit + // multiple tables during LTO each of which uses directory 0, referencing the + // comp_dir of all the type units that use it. + MCDwarfDwoLineTable SplitTypeUnitFileTable; -private: + // True iff there are multiple CUs in this module. + bool SingleCU; + + MCDwarfDwoLineTable *getDwoLineTable(const DwarfCompileUnit &); void addScopeVariable(LexicalScope *LS, DbgVariable *Var); + const SmallVectorImpl<DwarfUnit *> &getUnits() { + return InfoHolder.getUnits(); + } + /// \brief Find abstract variable associated with Var. DbgVariable *findAbstractVariable(DIVariable &Var, DebugLoc Loc); @@ -486,24 +426,30 @@ private: /// DW_AT_low_pc and DW_AT_high_pc attributes. If there are global /// variables in this scope then create and insert DIEs for these /// variables. - DIE *updateSubprogramScopeDIE(CompileUnit *SPCU, DISubprogram SP); + DIE *updateSubprogramScopeDIE(DwarfCompileUnit *SPCU, DISubprogram SP); + + /// \brief A helper function to check whether the DIE for a given Scope is + /// going to be null. + bool isLexicalScopeDIENull(LexicalScope *Scope); + + /// \brief A helper function to construct a RangeSpanList for a given + /// lexical scope. + void addScopeRangeList(DwarfCompileUnit *TheCU, DIE *ScopeDIE, + const SmallVectorImpl<InsnRange> &Range); /// \brief Construct new DW_TAG_lexical_block for this scope and /// attach DW_AT_low_pc/DW_AT_high_pc labels. - DIE *constructLexicalScopeDIE(CompileUnit *TheCU, LexicalScope *Scope); - /// A helper function to check whether the DIE for a given Scope is going - /// to be null. - bool isLexicalScopeDIENull(LexicalScope *Scope); + DIE *constructLexicalScopeDIE(DwarfCompileUnit *TheCU, LexicalScope *Scope); /// \brief This scope represents inlined body of a function. Construct /// DIE to represent this concrete inlined copy of the function. - DIE *constructInlinedScopeDIE(CompileUnit *TheCU, LexicalScope *Scope); + DIE *constructInlinedScopeDIE(DwarfCompileUnit *TheCU, LexicalScope *Scope); /// \brief Construct a DIE for this scope. - DIE *constructScopeDIE(CompileUnit *TheCU, LexicalScope *Scope); + DIE *constructScopeDIE(DwarfCompileUnit *TheCU, LexicalScope *Scope); /// A helper function to create children of a Scope DIE. - DIE *createScopeChildrenDIE(CompileUnit *TheCU, LexicalScope *Scope, - SmallVectorImpl<DIE*> &Children); + DIE *createScopeChildrenDIE(DwarfCompileUnit *TheCU, LexicalScope *Scope, + SmallVectorImpl<DIE *> &Children); /// \brief Emit initial Dwarf sections with a label at the start of each one. void emitSectionLabels(); @@ -528,9 +474,6 @@ private: /// open. void endSections(); - /// \brief Emit a set of abbreviations to the specific section. - void emitAbbrevs(const MCSection *, std::vector<DIEAbbrev*> *); - /// \brief Emit the debug info section. void emitDebugInfo(); @@ -566,32 +509,41 @@ private: /// index. void emitDebugPubTypes(bool GnuStyle = false); + void + emitDebugPubSection(bool GnuStyle, const MCSection *PSec, StringRef Name, + const StringMap<const DIE *> &(DwarfUnit::*Accessor)() + const); + /// \brief Emit visible names into a debug str section. void emitDebugStr(); /// \brief Emit visible names into a debug loc section. void emitDebugLoc(); + /// \brief Emit visible names into a debug loc dwo section. + void emitDebugLocDWO(); + /// \brief Emit visible names into a debug aranges section. void emitDebugARanges(); /// \brief Emit visible names into a debug ranges section. void emitDebugRanges(); - /// \brief Emit visible names into a debug macinfo section. - void emitDebugMacInfo(); - /// \brief Emit inline info using custom format. void emitDebugInlineInfo(); /// DWARF 5 Experimental Split Dwarf Emitters + /// \brief Initialize common features of skeleton units. + void initSkeletonUnit(const DwarfUnit *U, DIE *Die, DwarfUnit *NewU); + /// \brief Construct the split debug info compile unit for the debug info /// section. - CompileUnit *constructSkeletonCU(const CompileUnit *CU); + DwarfCompileUnit *constructSkeletonCU(const DwarfCompileUnit *CU); - /// \brief Emit the local split abbreviations. - void emitSkeletonAbbrevs(const MCSection *); + /// \brief Construct the split debug info compile unit for the debug info + /// section. + DwarfTypeUnit *constructSkeletonTU(DwarfTypeUnit *TU); /// \brief Emit the debug info dwo section. void emitDebugInfoDWO(); @@ -599,27 +551,33 @@ private: /// \brief Emit the debug abbrev dwo section. void emitDebugAbbrevDWO(); + /// \brief Emit the debug line dwo section. + void emitDebugLineDWO(); + /// \brief Emit the debug str dwo section. void emitDebugStrDWO(); - /// \brief Create new CompileUnit for the given metadata node with tag + /// Flags to let the linker know we have emitted new style pubnames. Only + /// emit it here if we don't have a skeleton CU for split dwarf. + void addGnuPubAttributes(DwarfUnit *U, DIE *D) const; + + /// \brief Create new DwarfCompileUnit for the given metadata node with tag /// DW_TAG_compile_unit. - CompileUnit *constructCompileUnit(DICompileUnit DIUnit); + DwarfCompileUnit *constructDwarfCompileUnit(DICompileUnit DIUnit); /// \brief Construct subprogram DIE. - void constructSubprogramDIE(CompileUnit *TheCU, const MDNode *N); + void constructSubprogramDIE(DwarfCompileUnit *TheCU, const MDNode *N); /// \brief Construct imported_module or imported_declaration DIE. - void constructImportedEntityDIE(CompileUnit *TheCU, const MDNode *N); + void constructImportedEntityDIE(DwarfCompileUnit *TheCU, const MDNode *N); /// \brief Construct import_module DIE. - void constructImportedEntityDIE(CompileUnit *TheCU, const MDNode *N, + void constructImportedEntityDIE(DwarfCompileUnit *TheCU, const MDNode *N, DIE *Context); /// \brief Construct import_module DIE. - void constructImportedEntityDIE(CompileUnit *TheCU, - const DIImportedEntity &Module, - DIE *Context); + void constructImportedEntityDIE(DwarfCompileUnit *TheCU, + const DIImportedEntity &Module, DIE *Context); /// \brief Register a source line with debug info. Returns the unique /// label that was emitted and which provides correspondence to the @@ -633,21 +591,18 @@ private: /// \brief If Var is an current function argument that add it in /// CurrentFnArguments list. - bool addCurrentFnArgument(const MachineFunction *MF, - DbgVariable *Var, LexicalScope *Scope); + bool addCurrentFnArgument(DbgVariable *Var, LexicalScope *Scope); /// \brief Populate LexicalScope entries with variables' info. - void collectVariableInfo(const MachineFunction *, - SmallPtrSet<const MDNode *, 16> &ProcessedVars); + void collectVariableInfo(SmallPtrSet<const MDNode *, 16> &ProcessedVars); /// \brief Collect variable information from the side table maintained /// by MMI. - void collectVariableInfoFromMMITable(const MachineFunction * MF, - SmallPtrSet<const MDNode *, 16> &P); + void collectVariableInfoFromMMITable(SmallPtrSet<const MDNode *, 16> &P); /// \brief Ensure that a label will be emitted before MI. void requestLabelBeforeInsn(const MachineInstr *MI) { - LabelsBeforeInsn.insert(std::make_pair(MI, (MCSymbol*)0)); + LabelsBeforeInsn.insert(std::make_pair(MI, (MCSymbol *)0)); } /// \brief Return Label preceding the instruction. @@ -655,12 +610,15 @@ private: /// \brief Ensure that a label will be emitted after MI. void requestLabelAfterInsn(const MachineInstr *MI) { - LabelsAfterInsn.insert(std::make_pair(MI, (MCSymbol*)0)); + LabelsAfterInsn.insert(std::make_pair(MI, (MCSymbol *)0)); } /// \brief Return Label immediately following the instruction. MCSymbol *getLabelAfterInsn(const MachineInstr *MI); + void attachLowHighPC(DwarfCompileUnit *Unit, DIE *D, MCSymbol *Begin, + MCSymbol *End); + public: //===--------------------------------------------------------------------===// // Main entry points. @@ -679,62 +637,89 @@ public: void beginModule(); /// \brief Emit all Dwarf sections that should come after the content. - void endModule(); + void endModule() override; /// \brief Gather pre-function debug information. - void beginFunction(const MachineFunction *MF); + void beginFunction(const MachineFunction *MF) override; /// \brief Gather and emit post-function debug information. - void endFunction(const MachineFunction *MF); + void endFunction(const MachineFunction *MF) override; /// \brief Process beginning of an instruction. - void beginInstruction(const MachineInstr *MI); + void beginInstruction(const MachineInstr *MI) override; /// \brief Process end of an instruction. - void endInstruction(const MachineInstr *MI); + void endInstruction() override; /// \brief Add a DIE to the set of types that we're going to pull into /// type units. - void addTypeUnitType(DIE *Die) { TypeUnits.push_back(Die); } + void addDwarfTypeUnitType(DwarfCompileUnit &CU, StringRef Identifier, + DIE *Die, DICompositeType CTy); /// \brief Add a label so that arange data can be generated for it. void addArangeLabel(SymbolCU SCU) { ArangeLabels.push_back(SCU); } /// \brief For symbols that have a size designated (e.g. common symbols), /// this tracks that size. - void setSymbolSize(const MCSymbol *Sym, uint64_t Size) { SymSize[Sym] = Size;} - - /// \brief Look up the source id with the given directory and source file - /// names. If none currently exists, create a new id and insert it in the - /// SourceIds map. - unsigned getOrCreateSourceID(StringRef DirName, StringRef FullName, - unsigned CUID); + void setSymbolSize(const MCSymbol *Sym, uint64_t Size) override { + SymSize[Sym] = Size; + } /// \brief Recursively Emits a debug information entry. - void emitDIE(DIE *Die, ArrayRef<DIEAbbrev *> Abbrevs); + void emitDIE(DIE *Die); // Experimental DWARF5 features. /// \brief Returns whether or not to emit tables that dwarf consumers can /// use to accelerate lookup. - bool useDwarfAccelTables() { return HasDwarfAccelTables; } + bool useDwarfAccelTables() const { return HasDwarfAccelTables; } /// \brief Returns whether or not to change the current debug info for the /// split dwarf proposal support. - bool useSplitDwarf() { return HasSplitDwarf; } + bool useSplitDwarf() const { return HasSplitDwarf; } /// Returns the Dwarf Version. unsigned getDwarfVersion() const { return DwarfVersion; } + /// Returns the section symbol for the .debug_loc section. + MCSymbol *getDebugLocSym() const { return DwarfDebugLocSectionSym; } + + /// Returns the previous section that was emitted into. + const MCSection *getPrevSection() const { return PrevSection; } + + /// Returns the previous CU that was being updated + const DwarfCompileUnit *getPrevCU() const { return PrevCU; } + + /// Returns the entries for the .debug_loc section. + const SmallVectorImpl<DebugLocList> & + getDebugLocEntries() const { + return DotDebugLocEntries; + } + + /// \brief Emit an entry for the debug loc section. This can be used to + /// handle an entry that's going to be emitted into the debug loc section. + void emitDebugLocEntry(ByteStreamer &Streamer, const DebugLocEntry &Entry); + + /// Emit the location for a debug loc entry, including the size header. + void emitDebugLocEntryLocation(const DebugLocEntry &Entry); + /// Find the MDNode for the given reference. template <typename T> T resolve(DIRef<T> Ref) const { return Ref.resolve(TypeIdentifierMap); } + /// \brief Return the TypeIdentifierMap. + const DITypeIdentifierMap &getTypeIdentifierMap() const { + return TypeIdentifierMap; + } + + /// Find the DwarfCompileUnit for the given CU Die. + DwarfCompileUnit *lookupUnit(const DIE *CU) const { + return CUDieMap.lookup(CU); + } /// isSubprogramContext - Return true if Context is either a subprogram /// or another context nested inside a subprogram. bool isSubprogramContext(const MDNode *Context); - }; } // End of namespace llvm diff --git a/lib/CodeGen/AsmPrinter/DwarfException.cpp b/lib/CodeGen/AsmPrinter/DwarfException.cpp index 7133458129..113a9e4cd4 100644 --- a/lib/CodeGen/AsmPrinter/DwarfException.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfException.cpp @@ -20,6 +20,7 @@ #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/IR/DataLayout.h" +#include "llvm/IR/Mangler.h" #include "llvm/IR/Module.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCContext.h" @@ -30,7 +31,7 @@ #include "llvm/Support/Dwarf.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/FormattedStream.h" -#include "llvm/Target/Mangler.h" +#include "llvm/Support/LEB128.h" #include "llvm/Target/TargetFrameLowering.h" #include "llvm/Target/TargetLoweringObjectFile.h" #include "llvm/Target/TargetOptions.h" @@ -57,19 +58,6 @@ unsigned DwarfException::SharedTypeIds(const LandingPadInfo *L, return Count; } -/// PadLT - Order landing pads lexicographically by type id. -bool DwarfException::PadLT(const LandingPadInfo *L, const LandingPadInfo *R) { - const std::vector<int> &LIds = L->TypeIds, &RIds = R->TypeIds; - unsigned LSize = LIds.size(), RSize = RIds.size(); - unsigned MinSize = LSize < RSize ? LSize : RSize; - - for (unsigned i = 0; i != MinSize; ++i) - if (LIds[i] != RIds[i]) - return LIds[i] < RIds[i]; - - return LSize < RSize; -} - /// ComputeActionsTable - Compute the actions table and gather the first action /// index for each landing pad site. unsigned DwarfException:: @@ -108,7 +96,7 @@ ComputeActionsTable(const SmallVectorImpl<const LandingPadInfo*> &LandingPads, for (std::vector<unsigned>::const_iterator I = FilterIds.begin(), E = FilterIds.end(); I != E; ++I) { FilterOffsets.push_back(Offset); - Offset -= MCAsmInfo::getULEB128Size(*I); + Offset -= getULEB128Size(*I); } FirstActions.reserve(LandingPads.size()); @@ -132,14 +120,12 @@ ComputeActionsTable(const SmallVectorImpl<const LandingPadInfo*> &LandingPads, unsigned SizePrevIds = PrevLPI->TypeIds.size(); assert(Actions.size()); PrevAction = Actions.size() - 1; - SizeAction = - MCAsmInfo::getSLEB128Size(Actions[PrevAction].NextAction) + - MCAsmInfo::getSLEB128Size(Actions[PrevAction].ValueForTypeID); + SizeAction = getSLEB128Size(Actions[PrevAction].NextAction) + + getSLEB128Size(Actions[PrevAction].ValueForTypeID); for (unsigned j = NumShared; j != SizePrevIds; ++j) { assert(PrevAction != (unsigned)-1 && "PrevAction is invalid!"); - SizeAction -= - MCAsmInfo::getSLEB128Size(Actions[PrevAction].ValueForTypeID); + SizeAction -= getSLEB128Size(Actions[PrevAction].ValueForTypeID); SizeAction += -Actions[PrevAction].NextAction; PrevAction = Actions[PrevAction].Previous; } @@ -150,10 +136,10 @@ ComputeActionsTable(const SmallVectorImpl<const LandingPadInfo*> &LandingPads, int TypeID = TypeIds[J]; assert(-1 - TypeID < (int)FilterOffsets.size() && "Unknown filter id!"); int ValueForTypeID = TypeID < 0 ? FilterOffsets[-1 - TypeID] : TypeID; - unsigned SizeTypeID = MCAsmInfo::getSLEB128Size(ValueForTypeID); + unsigned SizeTypeID = getSLEB128Size(ValueForTypeID); int NextAction = SizeAction ? -(SizeAction + SizeTypeID) : 0; - SizeAction = SizeTypeID + MCAsmInfo::getSLEB128Size(NextAction); + SizeAction = SizeTypeID + getSLEB128Size(NextAction); SizeSiteActions += SizeAction; ActionEntry Action = { ValueForTypeID, NextAction, PrevAction }; @@ -242,7 +228,7 @@ ComputeCallSiteTable(SmallVectorImpl<CallSiteEntry> &CallSites, I != E; ++I) { for (MachineBasicBlock::const_iterator MI = I->begin(), E = I->end(); MI != E; ++MI) { - if (!MI->isLabel()) { + if (!MI->isEHLabel()) { if (MI->isCall()) SawPotentiallyThrowing |= !CallToNoUnwindFunction(MI); continue; @@ -357,7 +343,10 @@ void DwarfException::EmitExceptionTable() { for (unsigned i = 0, N = PadInfos.size(); i != N; ++i) LandingPads.push_back(&PadInfos[i]); - std::sort(LandingPads.begin(), LandingPads.end(), PadLT); + // Order landing pads lexicographically by type id. + std::sort(LandingPads.begin(), LandingPads.end(), + [](const LandingPadInfo *L, + const LandingPadInfo *R) { return L->TypeIds < R->TypeIds; }); // Compute the actions table and gather the first action index for each // landing pad site. @@ -401,9 +390,9 @@ void DwarfException::EmitExceptionTable() { } for (unsigned i = 0, e = CallSites.size(); i < e; ++i) { - CallSiteTableLength += MCAsmInfo::getULEB128Size(CallSites[i].Action); + CallSiteTableLength += getULEB128Size(CallSites[i].Action); if (IsSJLJ) - CallSiteTableLength += MCAsmInfo::getULEB128Size(i); + CallSiteTableLength += getULEB128Size(i); } // Type infos. @@ -488,15 +477,14 @@ void DwarfException::EmitExceptionTable() { // We chose another solution: don't output padding inside the table like GCC // does, instead output it before the table. unsigned SizeTypes = TypeInfos.size() * TypeFormatSize; - unsigned CallSiteTableLengthSize = - MCAsmInfo::getULEB128Size(CallSiteTableLength); + unsigned CallSiteTableLengthSize = getULEB128Size(CallSiteTableLength); unsigned TTypeBaseOffset = sizeof(int8_t) + // Call site format CallSiteTableLengthSize + // Call site table length size CallSiteTableLength + // Call site table length SizeActions + // Actions size SizeTypes; - unsigned TTypeBaseOffsetSize = MCAsmInfo::getULEB128Size(TTypeBaseOffset); + unsigned TTypeBaseOffsetSize = getULEB128Size(TTypeBaseOffset); unsigned TotalSize = sizeof(int8_t) + // LPStart format sizeof(int8_t) + // TType format @@ -717,20 +705,19 @@ void DwarfException::EmitTypeInfos(unsigned TTypeEncoding) { } } -/// EndModule - Emit all exception information that should come after the +/// endModule - Emit all exception information that should come after the /// content. -void DwarfException::EndModule() { +void DwarfException::endModule() { llvm_unreachable("Should be implemented"); } -/// BeginFunction - Gather pre-function exception information. Assumes it's +/// beginFunction - Gather pre-function exception information. Assumes it's /// being emitted immediately after the function entry point. -void DwarfException::BeginFunction(const MachineFunction *MF) { +void DwarfException::beginFunction(const MachineFunction *MF) { llvm_unreachable("Should be implemented"); } -/// EndFunction - Gather and emit post-function exception information. -/// -void DwarfException::EndFunction() { +/// endFunction - Gather and emit post-function exception information. +void DwarfException::endFunction(const MachineFunction *) { llvm_unreachable("Should be implemented"); } diff --git a/lib/CodeGen/AsmPrinter/DwarfException.h b/lib/CodeGen/AsmPrinter/DwarfException.h index 15751615b7..f792482751 100644 --- a/lib/CodeGen/AsmPrinter/DwarfException.h +++ b/lib/CodeGen/AsmPrinter/DwarfException.h @@ -14,6 +14,7 @@ #ifndef LLVM_CODEGEN_ASMPRINTER_DWARFEXCEPTION_H #define LLVM_CODEGEN_ASMPRINTER_DWARFEXCEPTION_H +#include "AsmPrinterHandler.h" #include "llvm/ADT/DenseMap.h" #include "llvm/CodeGen/AsmPrinter.h" #include <vector> @@ -35,7 +36,7 @@ class AsmPrinter; //===----------------------------------------------------------------------===// /// DwarfException - Emits Dwarf exception handling directives. /// -class DwarfException { +class DwarfException : public AsmPrinterHandler { protected: /// Asm - Target of Dwarf emission. AsmPrinter *Asm; @@ -47,9 +48,6 @@ protected: static unsigned SharedTypeIds(const LandingPadInfo *L, const LandingPadInfo *R); - /// PadLT - Order landing pads lexicographically by type id. - static bool PadLT(const LandingPadInfo *L, const LandingPadInfo *R); - /// PadRange - Structure holding a try-range and the associated landing pad. struct PadRange { // The index of the landing pad. @@ -130,16 +128,21 @@ public: DwarfException(AsmPrinter *A); virtual ~DwarfException(); - /// EndModule - Emit all exception information that should come after the + /// endModule - Emit all exception information that should come after the /// content. - virtual void EndModule(); + void endModule() override; - /// BeginFunction - Gather pre-function exception information. Assumes being + /// beginFunction - Gather pre-function exception information. Assumes being /// emitted immediately after the function entry point. - virtual void BeginFunction(const MachineFunction *MF); + void beginFunction(const MachineFunction *MF) override; + + /// endFunction - Gather and emit post-function exception information. + void endFunction(const MachineFunction *) override; - /// EndFunction - Gather and emit post-function exception information. - virtual void EndFunction(); + // We don't need these. + void setSymbolSize(const MCSymbol *Sym, uint64_t Size) override {} + void beginInstruction(const MachineInstr *MI) override {} + void endInstruction() override {} }; class DwarfCFIException : public DwarfException { @@ -164,22 +167,26 @@ public: DwarfCFIException(AsmPrinter *A); virtual ~DwarfCFIException(); - /// EndModule - Emit all exception information that should come after the + /// endModule - Emit all exception information that should come after the /// content. - virtual void EndModule(); + void endModule() override; - /// BeginFunction - Gather pre-function exception information. Assumes being + /// beginFunction - Gather pre-function exception information. Assumes being /// emitted immediately after the function entry point. - virtual void BeginFunction(const MachineFunction *MF); + void beginFunction(const MachineFunction *MF) override; - /// EndFunction - Gather and emit post-function exception information. - virtual void EndFunction(); + /// endFunction - Gather and emit post-function exception information. + void endFunction(const MachineFunction *) override; }; class ARMException : public DwarfException { - void EmitTypeInfos(unsigned TTypeEncoding); + void EmitTypeInfos(unsigned TTypeEncoding) override; ARMTargetStreamer &getTargetStreamer(); + /// shouldEmitCFI - Per-function flag to indicate if frame CFI info + /// should be emitted. + bool shouldEmitCFI; + public: //===--------------------------------------------------------------------===// // Main entry points. @@ -187,16 +194,16 @@ public: ARMException(AsmPrinter *A); virtual ~ARMException(); - /// EndModule - Emit all exception information that should come after the + /// endModule - Emit all exception information that should come after the /// content. - virtual void EndModule(); + void endModule() override; - /// BeginFunction - Gather pre-function exception information. Assumes being + /// beginFunction - Gather pre-function exception information. Assumes being /// emitted immediately after the function entry point. - virtual void BeginFunction(const MachineFunction *MF); + void beginFunction(const MachineFunction *MF) override; - /// EndFunction - Gather and emit post-function exception information. - virtual void EndFunction(); + /// endFunction - Gather and emit post-function exception information. + void endFunction(const MachineFunction *) override; }; class Win64Exception : public DwarfException { @@ -219,16 +226,16 @@ public: Win64Exception(AsmPrinter *A); virtual ~Win64Exception(); - /// EndModule - Emit all exception information that should come after the + /// endModule - Emit all exception information that should come after the /// content. - virtual void EndModule(); + void endModule() override; - /// BeginFunction - Gather pre-function exception information. Assumes being + /// beginFunction - Gather pre-function exception information. Assumes being /// emitted immediately after the function entry point. - virtual void BeginFunction(const MachineFunction *MF); + void beginFunction(const MachineFunction *MF) override; - /// EndFunction - Gather and emit post-function exception information. - virtual void EndFunction(); + /// endFunction - Gather and emit post-function exception information. + void endFunction(const MachineFunction *) override; }; } // End of namespace llvm diff --git a/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp b/lib/CodeGen/AsmPrinter/DwarfUnit.cpp index a6ff953809..82e9bb008a 100644 --- a/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfUnit.cpp @@ -1,4 +1,4 @@ -//===-- llvm/CodeGen/DwarfCompileUnit.cpp - Dwarf Compile Unit ------------===// +//===-- llvm/CodeGen/DwarfUnit.cpp - Dwarf Type and Compile Units ---------===// // // The LLVM Compiler Infrastructure // @@ -13,50 +13,75 @@ #define DEBUG_TYPE "dwarfdebug" -#include "DwarfCompileUnit.h" +#include "DwarfUnit.h" #include "DwarfAccelTable.h" #include "DwarfDebug.h" #include "llvm/ADT/APFloat.h" -#include "llvm/DIBuilder.h" #include "llvm/IR/Constants.h" +#include "llvm/IR/DIBuilder.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/GlobalVariable.h" #include "llvm/IR/Instructions.h" +#include "llvm/IR/Mangler.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCContext.h" #include "llvm/MC/MCSection.h" #include "llvm/MC/MCStreamer.h" -#include "llvm/Target/Mangler.h" +#include "llvm/Support/CommandLine.h" #include "llvm/Target/TargetFrameLowering.h" -#include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetLoweringObjectFile.h" +#include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetRegisterInfo.h" using namespace llvm; -/// CompileUnit - Compile unit constructor. -CompileUnit::CompileUnit(unsigned UID, DIE *D, DICompileUnit Node, - AsmPrinter *A, DwarfDebug *DW, DwarfUnits *DWU) - : UniqueID(UID), Node(Node), CUDie(D), Asm(A), DD(DW), DU(DWU), - IndexTyDie(0), DebugInfoOffset(0) { +static cl::opt<bool> +GenerateDwarfTypeUnits("generate-type-units", cl::Hidden, + cl::desc("Generate DWARF4 type units."), + cl::init(false)); + +/// Unit - Unit constructor. +DwarfUnit::DwarfUnit(unsigned UID, DIE *D, DICompileUnit Node, AsmPrinter *A, + DwarfDebug *DW, DwarfFile *DWU) + : UniqueID(UID), CUNode(Node), UnitDie(D), DebugInfoOffset(0), Asm(A), + DD(DW), DU(DWU), IndexTyDie(0), Section(0), Skeleton(0) { DIEIntegerOne = new (DIEValueAllocator) DIEInteger(1); +} + +DwarfCompileUnit::DwarfCompileUnit(unsigned UID, DIE *D, DICompileUnit Node, + AsmPrinter *A, DwarfDebug *DW, + DwarfFile *DWU) + : DwarfUnit(UID, D, Node, A, DW, DWU) { insertDIE(Node, D); } -/// ~CompileUnit - Destructor for compile unit. -CompileUnit::~CompileUnit() { +DwarfTypeUnit::DwarfTypeUnit(unsigned UID, DIE *D, DwarfCompileUnit &CU, + AsmPrinter *A, DwarfDebug *DW, DwarfFile *DWU, + MCDwarfDwoLineTable *SplitLineTable) + : DwarfUnit(UID, D, CU.getCUNode(), A, DW, DWU), CU(CU), + SplitLineTable(SplitLineTable) { + if (SplitLineTable) + addSectionOffset(UnitDie.get(), dwarf::DW_AT_stmt_list, 0); +} + +/// ~Unit - Destructor for compile unit. +DwarfUnit::~DwarfUnit() { for (unsigned j = 0, M = DIEBlocks.size(); j < M; ++j) DIEBlocks[j]->~DIEBlock(); + for (unsigned j = 0, M = DIELocs.size(); j < M; ++j) + DIELocs[j]->~DIELoc(); } /// createDIEEntry - Creates a new DIEEntry to be a proxy for a debug /// information entry. -DIEEntry *CompileUnit::createDIEEntry(DIE *Entry) { +DIEEntry *DwarfUnit::createDIEEntry(DIE *Entry) { DIEEntry *Value = new (DIEValueAllocator) DIEEntry(Entry); return Value; } /// getDefaultLowerBound - Return the default lower bound for an array. If the /// DWARF version doesn't handle the language, return -1. -int64_t CompileUnit::getDefaultLowerBound() const { +int64_t DwarfUnit::getDefaultLowerBound() const { switch (getLanguage()) { default: break; @@ -100,17 +125,23 @@ int64_t CompileUnit::getDefaultLowerBound() const { /// Check whether the DIE for this MDNode can be shared across CUs. static bool isShareableAcrossCUs(DIDescriptor D) { - // When the MDNode can be part of the type system, the DIE can be - // shared across CUs. - return D.isType() || - (D.isSubprogram() && !DISubprogram(D).isDefinition()); + // When the MDNode can be part of the type system, the DIE can be shared + // across CUs. + // Combining type units and cross-CU DIE sharing is lower value (since + // cross-CU DIE sharing is used in LTO and removes type redundancy at that + // level already) but may be implementable for some value in projects + // building multiple independent libraries with LTO and then linking those + // together. + return (D.isType() || + (D.isSubprogram() && !DISubprogram(D).isDefinition())) && + !GenerateDwarfTypeUnits; } /// getDIE - Returns the debug information entry map slot for the /// specified debug variable. We delegate the request to DwarfDebug /// when the DIE for this MDNode can be shared across CUs. The mappings /// will be kept in DwarfDebug for shareable DIEs. -DIE *CompileUnit::getDIE(DIDescriptor D) const { +DIE *DwarfUnit::getDIE(DIDescriptor D) const { if (isShareableAcrossCUs(D)) return DD->getDIE(D); return MDNodeToDieMap.lookup(D); @@ -119,7 +150,7 @@ DIE *CompileUnit::getDIE(DIDescriptor D) const { /// insertDIE - Insert DIE into the map. We delegate the request to DwarfDebug /// when the DIE for this MDNode can be shared across CUs. The mappings /// will be kept in DwarfDebug for shareable DIEs. -void CompileUnit::insertDIE(DIDescriptor Desc, DIE *D) { +void DwarfUnit::insertDIE(DIDescriptor Desc, DIE *D) { if (isShareableAcrossCUs(Desc)) { DD->insertDIE(Desc, D); return; @@ -128,7 +159,7 @@ void CompileUnit::insertDIE(DIDescriptor Desc, DIE *D) { } /// addFlag - Add a flag that is true. -void CompileUnit::addFlag(DIE *Die, dwarf::Attribute Attribute) { +void DwarfUnit::addFlag(DIE *Die, dwarf::Attribute Attribute) { if (DD->getDwarfVersion() >= 4) Die->addValue(Attribute, dwarf::DW_FORM_flag_present, DIEIntegerOne); else @@ -137,8 +168,8 @@ void CompileUnit::addFlag(DIE *Die, dwarf::Attribute Attribute) { /// addUInt - Add an unsigned integer attribute data and value. /// -void CompileUnit::addUInt(DIE *Die, dwarf::Attribute Attribute, - Optional<dwarf::Form> Form, uint64_t Integer) { +void DwarfUnit::addUInt(DIE *Die, dwarf::Attribute Attribute, + Optional<dwarf::Form> Form, uint64_t Integer) { if (!Form) Form = DIEInteger::BestForm(false, Integer); DIEValue *Value = Integer == 1 ? DIEIntegerOne : new (DIEValueAllocator) @@ -146,22 +177,22 @@ void CompileUnit::addUInt(DIE *Die, dwarf::Attribute Attribute, Die->addValue(Attribute, *Form, Value); } -void CompileUnit::addUInt(DIEBlock *Block, dwarf::Form Form, uint64_t Integer) { +void DwarfUnit::addUInt(DIE *Block, dwarf::Form Form, uint64_t Integer) { addUInt(Block, (dwarf::Attribute)0, Form, Integer); } /// addSInt - Add an signed integer attribute data and value. /// -void CompileUnit::addSInt(DIE *Die, dwarf::Attribute Attribute, - Optional<dwarf::Form> Form, int64_t Integer) { +void DwarfUnit::addSInt(DIE *Die, dwarf::Attribute Attribute, + Optional<dwarf::Form> Form, int64_t Integer) { if (!Form) Form = DIEInteger::BestForm(true, Integer); DIEValue *Value = new (DIEValueAllocator) DIEInteger(Integer); Die->addValue(Attribute, *Form, Value); } -void CompileUnit::addSInt(DIEBlock *Die, Optional<dwarf::Form> Form, - int64_t Integer) { +void DwarfUnit::addSInt(DIELoc *Die, Optional<dwarf::Form> Form, + int64_t Integer) { addSInt(Die, (dwarf::Attribute)0, Form, Integer); } @@ -170,91 +201,135 @@ void CompileUnit::addSInt(DIEBlock *Die, Optional<dwarf::Form> Form, /// more predictable sizes. In the case of split dwarf we emit an index /// into another table which gets us the static offset into the string /// table. -void CompileUnit::addString(DIE *Die, dwarf::Attribute Attribute, - StringRef String) { - DIEValue *Value; - dwarf::Form Form; - if (!DD->useSplitDwarf()) { - MCSymbol *Symb = DU->getStringPoolEntry(String); - if (Asm->needsRelocationsForDwarfStringPool()) - Value = new (DIEValueAllocator) DIELabel(Symb); - else { - MCSymbol *StringPool = DU->getStringPoolSym(); - Value = new (DIEValueAllocator) DIEDelta(Symb, StringPool); - } - Form = dwarf::DW_FORM_strp; - } else { - unsigned idx = DU->getStringPoolIndex(String); - Value = new (DIEValueAllocator) DIEInteger(idx); - Form = dwarf::DW_FORM_GNU_str_index; - } +void DwarfUnit::addString(DIE *Die, dwarf::Attribute Attribute, + StringRef String) { + + if (!DD->useSplitDwarf()) + return addLocalString(Die, Attribute, String); + + unsigned idx = DU->getStringPoolIndex(String); + DIEValue *Value = new (DIEValueAllocator) DIEInteger(idx); DIEValue *Str = new (DIEValueAllocator) DIEString(Value, String); - Die->addValue(Attribute, Form, Str); + Die->addValue(Attribute, dwarf::DW_FORM_GNU_str_index, Str); } /// addLocalString - Add a string attribute data and value. This is guaranteed /// to be in the local string pool instead of indirected. -void CompileUnit::addLocalString(DIE *Die, dwarf::Attribute Attribute, - StringRef String) { +void DwarfUnit::addLocalString(DIE *Die, dwarf::Attribute Attribute, + StringRef String) { MCSymbol *Symb = DU->getStringPoolEntry(String); DIEValue *Value; - if (Asm->needsRelocationsForDwarfStringPool()) + if (Asm->MAI->doesDwarfUseRelocationsAcrossSections()) Value = new (DIEValueAllocator) DIELabel(Symb); else { MCSymbol *StringPool = DU->getStringPoolSym(); Value = new (DIEValueAllocator) DIEDelta(Symb, StringPool); } - Die->addValue(Attribute, dwarf::DW_FORM_strp, Value); + DIEValue *Str = new (DIEValueAllocator) DIEString(Value, String); + Die->addValue(Attribute, dwarf::DW_FORM_strp, Str); } /// addExpr - Add a Dwarf expression attribute data and value. /// -void CompileUnit::addExpr(DIEBlock *Die, dwarf::Form Form, const MCExpr *Expr) { +void DwarfUnit::addExpr(DIELoc *Die, dwarf::Form Form, const MCExpr *Expr) { DIEValue *Value = new (DIEValueAllocator) DIEExpr(Expr); Die->addValue((dwarf::Attribute)0, Form, Value); } +/// addLocationList - Add a Dwarf loclistptr attribute data and value. +/// +void DwarfUnit::addLocationList(DIE *Die, dwarf::Attribute Attribute, + unsigned Index) { + DIEValue *Value = new (DIEValueAllocator) DIELocList(Index); + dwarf::Form Form = DD->getDwarfVersion() >= 4 ? dwarf::DW_FORM_sec_offset + : dwarf::DW_FORM_data4; + Die->addValue(Attribute, Form, Value); +} + /// addLabel - Add a Dwarf label attribute data and value. /// -void CompileUnit::addLabel(DIE *Die, dwarf::Attribute Attribute, - dwarf::Form Form, const MCSymbol *Label) { +void DwarfUnit::addLabel(DIE *Die, dwarf::Attribute Attribute, dwarf::Form Form, + const MCSymbol *Label) { DIEValue *Value = new (DIEValueAllocator) DIELabel(Label); Die->addValue(Attribute, Form, Value); } -void CompileUnit::addLabel(DIEBlock *Die, dwarf::Form Form, - const MCSymbol *Label) { +void DwarfUnit::addLabel(DIELoc *Die, dwarf::Form Form, const MCSymbol *Label) { addLabel(Die, (dwarf::Attribute)0, Form, Label); } +/// addSectionLabel - Add a Dwarf section label attribute data and value. +/// +void DwarfUnit::addSectionLabel(DIE *Die, dwarf::Attribute Attribute, + const MCSymbol *Label) { + if (DD->getDwarfVersion() >= 4) + addLabel(Die, Attribute, dwarf::DW_FORM_sec_offset, Label); + else + addLabel(Die, Attribute, dwarf::DW_FORM_data4, Label); +} + +/// addSectionOffset - Add an offset into a section attribute data and value. +/// +void DwarfUnit::addSectionOffset(DIE *Die, dwarf::Attribute Attribute, + uint64_t Integer) { + if (DD->getDwarfVersion() >= 4) + addUInt(Die, Attribute, dwarf::DW_FORM_sec_offset, Integer); + else + addUInt(Die, Attribute, dwarf::DW_FORM_data4, Integer); +} + /// addLabelAddress - Add a dwarf label attribute data and value using /// DW_FORM_addr or DW_FORM_GNU_addr_index. /// -void CompileUnit::addLabelAddress(DIE *Die, dwarf::Attribute Attribute, - MCSymbol *Label) { +void DwarfCompileUnit::addLabelAddress(DIE *Die, dwarf::Attribute Attribute, + const MCSymbol *Label) { + + if (!DD->useSplitDwarf()) + return addLocalLabelAddress(Die, Attribute, Label); + if (Label) DD->addArangeLabel(SymbolCU(this, Label)); - if (!DD->useSplitDwarf()) { - if (Label != NULL) { - DIEValue *Value = new (DIEValueAllocator) DIELabel(Label); - Die->addValue(Attribute, dwarf::DW_FORM_addr, Value); - } else { - DIEValue *Value = new (DIEValueAllocator) DIEInteger(0); - Die->addValue(Attribute, dwarf::DW_FORM_addr, Value); - } + unsigned idx = DU->getAddrPoolIndex(Label); + DIEValue *Value = new (DIEValueAllocator) DIEInteger(idx); + Die->addValue(Attribute, dwarf::DW_FORM_GNU_addr_index, Value); +} + +void DwarfCompileUnit::addLocalLabelAddress(DIE *Die, + dwarf::Attribute Attribute, + const MCSymbol *Label) { + if (Label) + DD->addArangeLabel(SymbolCU(this, Label)); + + if (Label) { + DIEValue *Value = new (DIEValueAllocator) DIELabel(Label); + Die->addValue(Attribute, dwarf::DW_FORM_addr, Value); } else { - unsigned idx = DU->getAddrPoolIndex(Label); - DIEValue *Value = new (DIEValueAllocator) DIEInteger(idx); - Die->addValue(Attribute, dwarf::DW_FORM_GNU_addr_index, Value); + DIEValue *Value = new (DIEValueAllocator) DIEInteger(0); + Die->addValue(Attribute, dwarf::DW_FORM_addr, Value); } } +unsigned DwarfCompileUnit::getOrCreateSourceID(StringRef FileName, StringRef DirName) { + // If we print assembly, we can't separate .file entries according to + // compile units. Thus all files will belong to the default compile unit. + + // FIXME: add a better feature test than hasRawTextSupport. Even better, + // extend .file to support this. + return Asm->OutStreamer.EmitDwarfFileDirective( + 0, DirName, FileName, + Asm->OutStreamer.hasRawTextSupport() ? 0 : getUniqueID()); +} + +unsigned DwarfTypeUnit::getOrCreateSourceID(StringRef FileName, StringRef DirName) { + return SplitLineTable ? SplitLineTable->getFile(DirName, FileName) + : getCU().getOrCreateSourceID(FileName, DirName); +} + /// addOpAddress - Add a dwarf op address data and value using the /// form given and an op of either DW_FORM_addr or DW_FORM_GNU_addr_index. /// -void CompileUnit::addOpAddress(DIEBlock *Die, const MCSymbol *Sym) { - DD->addArangeLabel(SymbolCU(this, Sym)); +void DwarfUnit::addOpAddress(DIELoc *Die, const MCSymbol *Sym) { if (!DD->useSplitDwarf()) { addUInt(Die, dwarf::DW_FORM_data1, dwarf::DW_OP_addr); addLabel(Die, dwarf::DW_FORM_udata, Sym); @@ -264,31 +339,43 @@ void CompileUnit::addOpAddress(DIEBlock *Die, const MCSymbol *Sym) { } } -/// addDelta - Add a label delta attribute data and value. +/// addSectionDelta - Add a section label delta attribute data and value. /// -void CompileUnit::addDelta(DIE *Die, dwarf::Attribute Attribute, - dwarf::Form Form, const MCSymbol *Hi, - const MCSymbol *Lo) { +void DwarfUnit::addSectionDelta(DIE *Die, dwarf::Attribute Attribute, + const MCSymbol *Hi, const MCSymbol *Lo) { DIEValue *Value = new (DIEValueAllocator) DIEDelta(Hi, Lo); - Die->addValue(Attribute, Form, Value); + if (DD->getDwarfVersion() >= 4) + Die->addValue(Attribute, dwarf::DW_FORM_sec_offset, Value); + else + Die->addValue(Attribute, dwarf::DW_FORM_data4, Value); +} + +void DwarfUnit::addLabelDelta(DIE *Die, dwarf::Attribute Attribute, + const MCSymbol *Hi, const MCSymbol *Lo) { + DIEValue *Value = new (DIEValueAllocator) DIEDelta(Hi, Lo); + Die->addValue(Attribute, dwarf::DW_FORM_data4, Value); } /// addDIEEntry - Add a DIE attribute data and value. /// -void CompileUnit::addDIEEntry(DIE *Die, dwarf::Attribute Attribute, - DIE *Entry) { +void DwarfUnit::addDIEEntry(DIE *Die, dwarf::Attribute Attribute, DIE *Entry) { addDIEEntry(Die, Attribute, createDIEEntry(Entry)); } -void CompileUnit::addDIEEntry(DIE *Die, dwarf::Attribute Attribute, - DIEEntry *Entry) { - const DIE *DieCU = Die->getCompileUnitOrNull(); - const DIE *EntryCU = Entry->getEntry()->getCompileUnitOrNull(); +void DwarfUnit::addDIETypeSignature(DIE *Die, const DwarfTypeUnit &Type) { + Die->addValue(dwarf::DW_AT_signature, dwarf::DW_FORM_ref_sig8, + new (DIEValueAllocator) DIETypeSignature(Type)); +} + +void DwarfUnit::addDIEEntry(DIE *Die, dwarf::Attribute Attribute, + DIEEntry *Entry) { + const DIE *DieCU = Die->getUnitOrNull(); + const DIE *EntryCU = Entry->getEntry()->getUnitOrNull(); if (!DieCU) // We assume that Die belongs to this CU, if it is not linked to any CU yet. - DieCU = getCUDie(); + DieCU = getUnitDie(); if (!EntryCU) - EntryCU = getCUDie(); + EntryCU = getUnitDie(); Die->addValue(Attribute, EntryCU == DieCU ? dwarf::DW_FORM_ref4 : dwarf::DW_FORM_ref_addr, Entry); @@ -296,7 +383,7 @@ void CompileUnit::addDIEEntry(DIE *Die, dwarf::Attribute Attribute, /// Create a DIE with the given Tag, add the DIE to its parent, and /// call insertDIE if MD is not null. -DIE *CompileUnit::createAndAddDIE(unsigned Tag, DIE &Parent, DIDescriptor N) { +DIE *DwarfUnit::createAndAddDIE(unsigned Tag, DIE &Parent, DIDescriptor N) { DIE *Die = new DIE(Tag); Parent.addChild(Die); if (N) @@ -306,8 +393,14 @@ DIE *CompileUnit::createAndAddDIE(unsigned Tag, DIE &Parent, DIDescriptor N) { /// addBlock - Add block data. /// -void CompileUnit::addBlock(DIE *Die, dwarf::Attribute Attribute, - DIEBlock *Block) { +void DwarfUnit::addBlock(DIE *Die, dwarf::Attribute Attribute, DIELoc *Loc) { + Loc->ComputeSize(Asm); + DIELocs.push_back(Loc); // Memoize so we can call the destructor later on. + Die->addValue(Attribute, Loc->BestForm(DD->getDwarfVersion()), Loc); +} + +void DwarfUnit::addBlock(DIE *Die, dwarf::Attribute Attribute, + DIEBlock *Block) { Block->ComputeSize(Asm); DIEBlocks.push_back(Block); // Memoize so we can call the destructor later on. Die->addValue(Attribute, Block->BestForm(), Block); @@ -315,17 +408,12 @@ void CompileUnit::addBlock(DIE *Die, dwarf::Attribute Attribute, /// addSourceLine - Add location information to specified debug information /// entry. -void CompileUnit::addSourceLine(DIE *Die, DIVariable V) { - // Verify variable. - if (!V.isVariable()) - return; - - unsigned Line = V.getLineNumber(); +void DwarfUnit::addSourceLine(DIE *Die, unsigned Line, StringRef File, + StringRef Directory) { if (Line == 0) return; - unsigned FileID = - DD->getOrCreateSourceID(V.getContext().getFilename(), - V.getContext().getDirectory(), getUniqueID()); + + unsigned FileID = getOrCreateSourceID(File, Directory); assert(FileID && "Invalid file id"); addUInt(Die, dwarf::DW_AT_decl_file, None, FileID); addUInt(Die, dwarf::DW_AT_decl_line, None, Line); @@ -333,98 +421,59 @@ void CompileUnit::addSourceLine(DIE *Die, DIVariable V) { /// addSourceLine - Add location information to specified debug information /// entry. -void CompileUnit::addSourceLine(DIE *Die, DIGlobalVariable G) { - // Verify global variable. - if (!G.isGlobalVariable()) - return; +void DwarfUnit::addSourceLine(DIE *Die, DIVariable V) { + assert(V.isVariable()); - unsigned Line = G.getLineNumber(); - if (Line == 0) - return; - unsigned FileID = - DD->getOrCreateSourceID(G.getFilename(), G.getDirectory(), getUniqueID()); - assert(FileID && "Invalid file id"); - addUInt(Die, dwarf::DW_AT_decl_file, None, FileID); - addUInt(Die, dwarf::DW_AT_decl_line, None, Line); + addSourceLine(Die, V.getLineNumber(), V.getContext().getFilename(), + V.getContext().getDirectory()); } /// addSourceLine - Add location information to specified debug information /// entry. -void CompileUnit::addSourceLine(DIE *Die, DISubprogram SP) { - // Verify subprogram. - if (!SP.isSubprogram()) - return; +void DwarfUnit::addSourceLine(DIE *Die, DIGlobalVariable G) { + assert(G.isGlobalVariable()); - // If the line number is 0, don't add it. - unsigned Line = SP.getLineNumber(); - if (Line == 0) - return; + addSourceLine(Die, G.getLineNumber(), G.getFilename(), G.getDirectory()); +} - unsigned FileID = DD->getOrCreateSourceID(SP.getFilename(), SP.getDirectory(), - getUniqueID()); - assert(FileID && "Invalid file id"); - addUInt(Die, dwarf::DW_AT_decl_file, None, FileID); - addUInt(Die, dwarf::DW_AT_decl_line, None, Line); +/// addSourceLine - Add location information to specified debug information +/// entry. +void DwarfUnit::addSourceLine(DIE *Die, DISubprogram SP) { + assert(SP.isSubprogram()); + + addSourceLine(Die, SP.getLineNumber(), SP.getFilename(), SP.getDirectory()); } /// addSourceLine - Add location information to specified debug information /// entry. -void CompileUnit::addSourceLine(DIE *Die, DIType Ty) { - // Verify type. - if (!Ty.isType()) - return; +void DwarfUnit::addSourceLine(DIE *Die, DIType Ty) { + assert(Ty.isType()); - unsigned Line = Ty.getLineNumber(); - if (Line == 0) - return; - unsigned FileID = DD->getOrCreateSourceID(Ty.getFilename(), Ty.getDirectory(), - getUniqueID()); - assert(FileID && "Invalid file id"); - addUInt(Die, dwarf::DW_AT_decl_file, None, FileID); - addUInt(Die, dwarf::DW_AT_decl_line, None, Line); + addSourceLine(Die, Ty.getLineNumber(), Ty.getFilename(), Ty.getDirectory()); } /// addSourceLine - Add location information to specified debug information /// entry. -void CompileUnit::addSourceLine(DIE *Die, DIObjCProperty Ty) { - // Verify type. - if (!Ty.isObjCProperty()) - return; +void DwarfUnit::addSourceLine(DIE *Die, DIObjCProperty Ty) { + assert(Ty.isObjCProperty()); - unsigned Line = Ty.getLineNumber(); - if (Line == 0) - return; DIFile File = Ty.getFile(); - unsigned FileID = DD->getOrCreateSourceID(File.getFilename(), - File.getDirectory(), getUniqueID()); - assert(FileID && "Invalid file id"); - addUInt(Die, dwarf::DW_AT_decl_file, None, FileID); - addUInt(Die, dwarf::DW_AT_decl_line, None, Line); + addSourceLine(Die, Ty.getLineNumber(), File.getFilename(), + File.getDirectory()); } /// addSourceLine - Add location information to specified debug information /// entry. -void CompileUnit::addSourceLine(DIE *Die, DINameSpace NS) { - // Verify namespace. - if (!NS.Verify()) - return; - - unsigned Line = NS.getLineNumber(); - if (Line == 0) - return; - StringRef FN = NS.getFilename(); +void DwarfUnit::addSourceLine(DIE *Die, DINameSpace NS) { + assert(NS.Verify()); - unsigned FileID = - DD->getOrCreateSourceID(FN, NS.getDirectory(), getUniqueID()); - assert(FileID && "Invalid file id"); - addUInt(Die, dwarf::DW_AT_decl_file, None, FileID); - addUInt(Die, dwarf::DW_AT_decl_line, None, Line); + addSourceLine(Die, NS.getLineNumber(), NS.getFilename(), NS.getDirectory()); } /// addVariableAddress - Add DW_AT_location attribute for a /// DbgVariable based on provided MachineLocation. -void CompileUnit::addVariableAddress(const DbgVariable &DV, DIE *Die, - MachineLocation Location) { +void DwarfUnit::addVariableAddress(const DbgVariable &DV, DIE *Die, + MachineLocation Location) { if (DV.variableHasComplexAddress()) addComplexAddress(DV, Die, dwarf::DW_AT_location, Location); else if (DV.isBlockByrefVariable()) @@ -435,20 +484,53 @@ void CompileUnit::addVariableAddress(const DbgVariable &DV, DIE *Die, } /// addRegisterOp - Add register operand. -void CompileUnit::addRegisterOp(DIEBlock *TheDie, unsigned Reg) { +void DwarfUnit::addRegisterOp(DIELoc *TheDie, unsigned Reg) { const TargetRegisterInfo *RI = Asm->TM.getRegisterInfo(); - unsigned DWReg = RI->getDwarfRegNum(Reg, false); + int DWReg = RI->getDwarfRegNum(Reg, false); + bool isSubRegister = DWReg < 0; + + unsigned Idx = 0; + + // Go up the super-register chain until we hit a valid dwarf register number. + for (MCSuperRegIterator SR(Reg, RI); SR.isValid() && DWReg < 0; ++SR) { + DWReg = RI->getDwarfRegNum(*SR, false); + if (DWReg >= 0) + Idx = RI->getSubRegIndex(*SR, Reg); + } + + if (DWReg < 0) { + DEBUG(dbgs() << "Invalid Dwarf register number.\n"); + addUInt(TheDie, dwarf::DW_FORM_data1, dwarf::DW_OP_nop); + return; + } + + // Emit register if (DWReg < 32) addUInt(TheDie, dwarf::DW_FORM_data1, dwarf::DW_OP_reg0 + DWReg); else { addUInt(TheDie, dwarf::DW_FORM_data1, dwarf::DW_OP_regx); addUInt(TheDie, dwarf::DW_FORM_udata, DWReg); } + + // Emit Mask + if (isSubRegister) { + unsigned Size = RI->getSubRegIdxSize(Idx); + unsigned Offset = RI->getSubRegIdxOffset(Idx); + if (Offset > 0) { + addUInt(TheDie, dwarf::DW_FORM_data1, dwarf::DW_OP_bit_piece); + addUInt(TheDie, dwarf::DW_FORM_data1, Size); + addUInt(TheDie, dwarf::DW_FORM_data1, Offset); + } else { + unsigned ByteSize = Size / 8; // Assuming 8 bits per byte. + addUInt(TheDie, dwarf::DW_FORM_data1, dwarf::DW_OP_piece); + addUInt(TheDie, dwarf::DW_FORM_data1, ByteSize); + } + } } /// addRegisterOffset - Add register offset. -void CompileUnit::addRegisterOffset(DIEBlock *TheDie, unsigned Reg, - int64_t Offset) { +void DwarfUnit::addRegisterOffset(DIELoc *TheDie, unsigned Reg, + int64_t Offset) { const TargetRegisterInfo *RI = Asm->TM.getRegisterInfo(); unsigned DWReg = RI->getDwarfRegNum(Reg, false); const TargetRegisterInfo *TRI = Asm->TM.getRegisterInfo(); @@ -466,59 +548,59 @@ void CompileUnit::addRegisterOffset(DIEBlock *TheDie, unsigned Reg, /// addAddress - Add an address attribute to a die based on the location /// provided. -void CompileUnit::addAddress(DIE *Die, dwarf::Attribute Attribute, - const MachineLocation &Location, bool Indirect) { - DIEBlock *Block = new (DIEValueAllocator) DIEBlock(); +void DwarfUnit::addAddress(DIE *Die, dwarf::Attribute Attribute, + const MachineLocation &Location, bool Indirect) { + DIELoc *Loc = new (DIEValueAllocator) DIELoc(); if (Location.isReg() && !Indirect) - addRegisterOp(Block, Location.getReg()); + addRegisterOp(Loc, Location.getReg()); else { - addRegisterOffset(Block, Location.getReg(), Location.getOffset()); + addRegisterOffset(Loc, Location.getReg(), Location.getOffset()); if (Indirect && !Location.isReg()) { - addUInt(Block, dwarf::DW_FORM_data1, dwarf::DW_OP_deref); + addUInt(Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_deref); } } // Now attach the location information to the DIE. - addBlock(Die, Attribute, Block); + addBlock(Die, Attribute, Loc); } /// addComplexAddress - Start with the address based on the location provided, /// and generate the DWARF information necessary to find the actual variable -/// given the extra address information encoded in the DIVariable, starting from -/// the starting location. Add the DWARF information to the die. +/// given the extra address information encoded in the DbgVariable, starting +/// from the starting location. Add the DWARF information to the die. /// -void CompileUnit::addComplexAddress(const DbgVariable &DV, DIE *Die, - dwarf::Attribute Attribute, - const MachineLocation &Location) { - DIEBlock *Block = new (DIEValueAllocator) DIEBlock(); +void DwarfUnit::addComplexAddress(const DbgVariable &DV, DIE *Die, + dwarf::Attribute Attribute, + const MachineLocation &Location) { + DIELoc *Loc = new (DIEValueAllocator) DIELoc(); unsigned N = DV.getNumAddrElements(); unsigned i = 0; if (Location.isReg()) { if (N >= 2 && DV.getAddrElement(0) == DIBuilder::OpPlus) { // If first address element is OpPlus then emit // DW_OP_breg + Offset instead of DW_OP_reg + Offset. - addRegisterOffset(Block, Location.getReg(), DV.getAddrElement(1)); + addRegisterOffset(Loc, Location.getReg(), DV.getAddrElement(1)); i = 2; } else - addRegisterOp(Block, Location.getReg()); + addRegisterOp(Loc, Location.getReg()); } else - addRegisterOffset(Block, Location.getReg(), Location.getOffset()); + addRegisterOffset(Loc, Location.getReg(), Location.getOffset()); for (; i < N; ++i) { uint64_t Element = DV.getAddrElement(i); if (Element == DIBuilder::OpPlus) { - addUInt(Block, dwarf::DW_FORM_data1, dwarf::DW_OP_plus_uconst); - addUInt(Block, dwarf::DW_FORM_udata, DV.getAddrElement(++i)); + addUInt(Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_plus_uconst); + addUInt(Loc, dwarf::DW_FORM_udata, DV.getAddrElement(++i)); } else if (Element == DIBuilder::OpDeref) { if (!Location.isReg()) - addUInt(Block, dwarf::DW_FORM_data1, dwarf::DW_OP_deref); + addUInt(Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_deref); } else llvm_unreachable("unknown DIBuilder Opcode"); } // Now attach the location information to the DIE. - addBlock(Die, Attribute, Block); + addBlock(Die, Attribute, Loc); } /* Byref variables, in Blocks, are declared by the programmer as "SomeType @@ -581,9 +663,9 @@ void CompileUnit::addComplexAddress(const DbgVariable &DV, DIE *Die, /// starting location. Add the DWARF information to the die. For /// more information, read large comment just above here. /// -void CompileUnit::addBlockByrefAddress(const DbgVariable &DV, DIE *Die, - dwarf::Attribute Attribute, - const MachineLocation &Location) { +void DwarfUnit::addBlockByrefAddress(const DbgVariable &DV, DIE *Die, + dwarf::Attribute Attribute, + const MachineLocation &Location) { DIType Ty = DV.getType(); DIType TmpTy = Ty; uint16_t Tag = Ty.getTag(); @@ -620,40 +702,40 @@ void CompileUnit::addBlockByrefAddress(const DbgVariable &DV, DIE *Die, // Decode the original location, and use that as the start of the byref // variable's location. - DIEBlock *Block = new (DIEValueAllocator) DIEBlock(); + DIELoc *Loc = new (DIEValueAllocator) DIELoc(); if (Location.isReg()) - addRegisterOp(Block, Location.getReg()); + addRegisterOp(Loc, Location.getReg()); else - addRegisterOffset(Block, Location.getReg(), Location.getOffset()); + addRegisterOffset(Loc, Location.getReg(), Location.getOffset()); // If we started with a pointer to the __Block_byref... struct, then // the first thing we need to do is dereference the pointer (DW_OP_deref). if (isPointer) - addUInt(Block, dwarf::DW_FORM_data1, dwarf::DW_OP_deref); + addUInt(Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_deref); // Next add the offset for the '__forwarding' field: // DW_OP_plus_uconst ForwardingFieldOffset. Note there's no point in // adding the offset if it's 0. if (forwardingFieldOffset > 0) { - addUInt(Block, dwarf::DW_FORM_data1, dwarf::DW_OP_plus_uconst); - addUInt(Block, dwarf::DW_FORM_udata, forwardingFieldOffset); + addUInt(Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_plus_uconst); + addUInt(Loc, dwarf::DW_FORM_udata, forwardingFieldOffset); } // Now dereference the __forwarding field to get to the real __Block_byref // struct: DW_OP_deref. - addUInt(Block, dwarf::DW_FORM_data1, dwarf::DW_OP_deref); + addUInt(Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_deref); // Now that we've got the real __Block_byref... struct, add the offset // for the variable's field to get to the location of the actual variable: // DW_OP_plus_uconst varFieldOffset. Again, don't add if it's 0. if (varFieldOffset > 0) { - addUInt(Block, dwarf::DW_FORM_data1, dwarf::DW_OP_plus_uconst); - addUInt(Block, dwarf::DW_FORM_udata, varFieldOffset); + addUInt(Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_plus_uconst); + addUInt(Loc, dwarf::DW_FORM_udata, varFieldOffset); } // Now attach the location information to the DIE. - addBlock(Die, Attribute, Block); + addBlock(Die, Attribute, Loc); } /// isTypeSigned - Return true if the type is signed. @@ -698,8 +780,9 @@ static uint64_t getBaseTypeSize(DwarfDebug *DD, DIDerivedType Ty) { DIType BaseType = DD->resolve(Ty.getTypeDerivedFrom()); - // If this type is not derived from any type then take conservative approach. - if (!BaseType.isValid()) + // If this type is not derived from any type or the type is a declaration then + // take conservative approach. + if (!BaseType.isValid() || BaseType.isForwardDecl()) return Ty.getSizeInBits(); // If this is a derived type, go ahead and get the base type, unless it's a @@ -716,8 +799,8 @@ static uint64_t getBaseTypeSize(DwarfDebug *DD, DIDerivedType Ty) { } /// addConstantValue - Add constant value entry in variable DIE. -void CompileUnit::addConstantValue(DIE *Die, const MachineOperand &MO, - DIType Ty) { +void DwarfUnit::addConstantValue(DIE *Die, const MachineOperand &MO, + DIType Ty) { // FIXME: This is a bit conservative/simple - it emits negative values at // their maximum bit width which is a bit unfortunate (& doesn't prefer // udata/sdata over dataN as suggested by the DWARF spec) @@ -755,7 +838,7 @@ void CompileUnit::addConstantValue(DIE *Die, const MachineOperand &MO, } /// addConstantFPValue - Add constant value entry in variable DIE. -void CompileUnit::addConstantFPValue(DIE *Die, const MachineOperand &MO) { +void DwarfUnit::addConstantFPValue(DIE *Die, const MachineOperand &MO) { assert(MO.isFPImm() && "Invalid machine operand!"); DIEBlock *Block = new (DIEValueAllocator) DIEBlock(); APFloat FPImm = MO.getFPImm()->getValueAPF(); @@ -778,19 +861,19 @@ void CompileUnit::addConstantFPValue(DIE *Die, const MachineOperand &MO) { } /// addConstantFPValue - Add constant value entry in variable DIE. -void CompileUnit::addConstantFPValue(DIE *Die, const ConstantFP *CFP) { +void DwarfUnit::addConstantFPValue(DIE *Die, const ConstantFP *CFP) { // Pass this down to addConstantValue as an unsigned bag of bits. addConstantValue(Die, CFP->getValueAPF().bitcastToAPInt(), true); } /// addConstantValue - Add constant value entry in variable DIE. -void CompileUnit::addConstantValue(DIE *Die, const ConstantInt *CI, - bool Unsigned) { +void DwarfUnit::addConstantValue(DIE *Die, const ConstantInt *CI, + bool Unsigned) { addConstantValue(Die, CI->getValue(), Unsigned); } // addConstantValue - Add constant value entry in variable DIE. -void CompileUnit::addConstantValue(DIE *Die, const APInt &Val, bool Unsigned) { +void DwarfUnit::addConstantValue(DIE *Die, const APInt &Val, bool Unsigned) { unsigned CIBitWidth = Val.getBitWidth(); if (CIBitWidth <= 64) { // If we're a signed constant definitely use sdata. @@ -846,7 +929,7 @@ void CompileUnit::addConstantValue(DIE *Die, const APInt &Val, bool Unsigned) { } /// addTemplateParams - Add template parameters into buffer. -void CompileUnit::addTemplateParams(DIE &Buffer, DIArray TParams) { +void DwarfUnit::addTemplateParams(DIE &Buffer, DIArray TParams) { // Add template parameters. for (unsigned i = 0, e = TParams.getNumElements(); i != e; ++i) { DIDescriptor Element = TParams.getElement(i); @@ -860,9 +943,9 @@ void CompileUnit::addTemplateParams(DIE &Buffer, DIArray TParams) { } /// getOrCreateContextDIE - Get context owner's DIE. -DIE *CompileUnit::getOrCreateContextDIE(DIScope Context) { +DIE *DwarfUnit::getOrCreateContextDIE(DIScope Context) { if (!Context || Context.isFile()) - return getCUDie(); + return getUnitDie(); if (Context.isType()) return getOrCreateTypeDIE(DIType(Context)); if (Context.isNameSpace()) @@ -872,18 +955,38 @@ DIE *CompileUnit::getOrCreateContextDIE(DIScope Context) { return getDIE(Context); } +DIE *DwarfUnit::createTypeDIE(DICompositeType Ty) { + DIScope Context = resolve(Ty.getContext()); + DIE *ContextDIE = getOrCreateContextDIE(Context); + + DIE *TyDIE = getDIE(Ty); + if (TyDIE) + return TyDIE; + + // Create new type. + TyDIE = createAndAddDIE(Ty.getTag(), *ContextDIE, Ty); + + constructTypeDIE(*TyDIE, Ty); + + updateAcceleratorTables(Context, Ty, TyDIE); + return TyDIE; +} + /// getOrCreateTypeDIE - Find existing DIE or create new DIE for the /// given DIType. -DIE *CompileUnit::getOrCreateTypeDIE(const MDNode *TyNode) { +DIE *DwarfUnit::getOrCreateTypeDIE(const MDNode *TyNode) { if (!TyNode) return NULL; DIType Ty(TyNode); assert(Ty.isType()); + assert(Ty == resolve(Ty.getRef()) && + "type was not uniqued, possible ODR violation."); // Construct the context before querying for the existence of the DIE in case // such construction creates the DIE. - DIE *ContextDIE = getOrCreateContextDIE(resolve(Ty.getContext())); + DIScope Context = resolve(Ty.getContext()); + DIE *ContextDIE = getOrCreateContextDIE(Context); assert(ContextDIE); DIE *TyDIE = getDIE(Ty); @@ -893,16 +996,29 @@ DIE *CompileUnit::getOrCreateTypeDIE(const MDNode *TyNode) { // Create new type. TyDIE = createAndAddDIE(Ty.getTag(), *ContextDIE, Ty); + updateAcceleratorTables(Context, Ty, TyDIE); + if (Ty.isBasicType()) constructTypeDIE(*TyDIE, DIBasicType(Ty)); - else if (Ty.isCompositeType()) - constructTypeDIE(*TyDIE, DICompositeType(Ty)); - else { + else if (Ty.isCompositeType()) { + DICompositeType CTy(Ty); + if (GenerateDwarfTypeUnits && !Ty.isForwardDecl()) + if (MDString *TypeId = CTy.getIdentifier()) { + DD->addDwarfTypeUnitType(getCU(), TypeId->getString(), TyDIE, CTy); + // Skip updating the accelerator tables since this is not the full type. + return TyDIE; + } + constructTypeDIE(*TyDIE, CTy); + } else { assert(Ty.isDerivedType() && "Unknown kind of DIType"); constructTypeDIE(*TyDIE, DIDerivedType(Ty)); } - // If this is a named finished type then include it in the list of types - // for the accelerator tables. + + return TyDIE; +} + +void DwarfUnit::updateAcceleratorTables(DIScope Context, DIType Ty, + const DIE *TyDIE) { if (!Ty.getName().empty() && !Ty.isForwardDecl()) { bool IsImplementation = 0; if (Ty.isCompositeType()) { @@ -913,13 +1029,16 @@ DIE *CompileUnit::getOrCreateTypeDIE(const MDNode *TyNode) { } unsigned Flags = IsImplementation ? dwarf::DW_FLAG_type_implementation : 0; addAccelType(Ty.getName(), std::make_pair(TyDIE, Flags)); - } - return TyDIE; + if ((!Context || Context.isCompileUnit() || Context.isFile() || + Context.isNameSpace()) && + getCUNode().getEmissionKind() != DIBuilder::LineTablesOnly) + GlobalTypes[getParentContextString(Context) + Ty.getName().str()] = TyDIE; + } } /// addType - Add a new type attribute to the specified entity. -void CompileUnit::addType(DIE *Entity, DIType Ty, dwarf::Attribute Attribute) { +void DwarfUnit::addType(DIE *Entity, DIType Ty, dwarf::Attribute Attribute) { assert(Ty && "Trying to add a type that doesn't exist?"); // Check for pre-existence. @@ -937,66 +1056,59 @@ void CompileUnit::addType(DIE *Entity, DIType Ty, dwarf::Attribute Attribute) { Entry = createDIEEntry(Buffer); insertDIEEntry(Ty, Entry); addDIEEntry(Entity, Attribute, Entry); - - // If this is a complete composite type then include it in the - // list of global types. - addGlobalType(Ty); } // Accelerator table mutators - add each name along with its companion // DIE to the proper table while ensuring that the name that we're going // to reference is in the string table. We do this since the names we // add may not only be identical to the names in the DIE. -void CompileUnit::addAccelName(StringRef Name, DIE *Die) { +void DwarfUnit::addAccelName(StringRef Name, const DIE *Die) { + if (!DD->useDwarfAccelTables()) + return; DU->getStringPoolEntry(Name); - std::vector<DIE *> &DIEs = AccelNames[Name]; + std::vector<const DIE *> &DIEs = AccelNames[Name]; DIEs.push_back(Die); } -void CompileUnit::addAccelObjC(StringRef Name, DIE *Die) { +void DwarfUnit::addAccelObjC(StringRef Name, const DIE *Die) { + if (!DD->useDwarfAccelTables()) + return; DU->getStringPoolEntry(Name); - std::vector<DIE *> &DIEs = AccelObjC[Name]; + std::vector<const DIE *> &DIEs = AccelObjC[Name]; DIEs.push_back(Die); } -void CompileUnit::addAccelNamespace(StringRef Name, DIE *Die) { +void DwarfUnit::addAccelNamespace(StringRef Name, const DIE *Die) { + if (!DD->useDwarfAccelTables()) + return; DU->getStringPoolEntry(Name); - std::vector<DIE *> &DIEs = AccelNamespace[Name]; + std::vector<const DIE *> &DIEs = AccelNamespace[Name]; DIEs.push_back(Die); } -void CompileUnit::addAccelType(StringRef Name, std::pair<DIE *, unsigned> Die) { +void DwarfUnit::addAccelType(StringRef Name, + std::pair<const DIE *, unsigned> Die) { + if (!DD->useDwarfAccelTables()) + return; DU->getStringPoolEntry(Name); - std::vector<std::pair<DIE *, unsigned> > &DIEs = AccelTypes[Name]; + std::vector<std::pair<const DIE *, unsigned> > &DIEs = AccelTypes[Name]; DIEs.push_back(Die); } /// addGlobalName - Add a new global name to the compile unit. -void CompileUnit::addGlobalName(StringRef Name, DIE *Die, DIScope Context) { +void DwarfUnit::addGlobalName(StringRef Name, DIE *Die, DIScope Context) { + if (getCUNode().getEmissionKind() == DIBuilder::LineTablesOnly) + return; std::string FullName = getParentContextString(Context) + Name.str(); GlobalNames[FullName] = Die; } -/// addGlobalType - Add a new global type to the compile unit. -/// -void CompileUnit::addGlobalType(DIType Ty) { - DIScope Context = resolve(Ty.getContext()); - if (!Ty.getName().empty() && !Ty.isForwardDecl() && - (!Context || Context.isCompileUnit() || Context.isFile() || - Context.isNameSpace())) - if (DIEEntry *Entry = getDIEEntry(Ty)) { - std::string FullName = - getParentContextString(Context) + Ty.getName().str(); - GlobalTypes[FullName] = Entry->getEntry(); - } -} - /// getParentContextString - Walks the metadata parent chain in a language /// specific manner (using the compile unit language) and returns /// it as a string. This is done at the metadata level because DIEs may /// not currently have been added to the parent context and walking the /// DIEs looking for names is more expensive than walking the metadata. -std::string CompileUnit::getParentContextString(DIScope Context) const { +std::string DwarfUnit::getParentContextString(DIScope Context) const { if (!Context) return ""; @@ -1031,24 +1143,8 @@ std::string CompileUnit::getParentContextString(DIScope Context) const { return CS; } -/// addPubTypes - Add subprogram argument types for pubtypes section. -void CompileUnit::addPubTypes(DISubprogram SP) { - DICompositeType SPTy = SP.getType(); - uint16_t SPTag = SPTy.getTag(); - if (SPTag != dwarf::DW_TAG_subroutine_type) - return; - - DIArray Args = SPTy.getTypeArray(); - for (unsigned i = 0, e = Args.getNumElements(); i != e; ++i) { - DIType ATy(Args.getElement(i)); - if (!ATy.isType()) - continue; - addGlobalType(ATy); - } -} - /// constructTypeDIE - Construct basic type die from DIBasicType. -void CompileUnit::constructTypeDIE(DIE &Buffer, DIBasicType BTy) { +void DwarfUnit::constructTypeDIE(DIE &Buffer, DIBasicType BTy) { // Get core information. StringRef Name = BTy.getName(); // Add name if not anonymous or intermediate type. @@ -1067,7 +1163,7 @@ void CompileUnit::constructTypeDIE(DIE &Buffer, DIBasicType BTy) { } /// constructTypeDIE - Construct derived type die from DIDerivedType. -void CompileUnit::constructTypeDIE(DIE &Buffer, DIDerivedType DTy) { +void DwarfUnit::constructTypeDIE(DIE &Buffer, DIDerivedType DTy) { // Get core information. StringRef Name = DTy.getName(); uint64_t Size = DTy.getSizeInBits() >> 3; @@ -1094,40 +1190,25 @@ void CompileUnit::constructTypeDIE(DIE &Buffer, DIDerivedType DTy) { addSourceLine(&Buffer, DTy); } -/// Return true if the type is appropriately scoped to be contained inside -/// its own type unit. -static bool isTypeUnitScoped(DIType Ty, const DwarfDebug *DD) { - DIScope Parent = DD->resolve(Ty.getContext()); - while (Parent) { - // Don't generate a hash for anything scoped inside a function. - if (Parent.isSubprogram()) - return false; - Parent = DD->resolve(Parent.getContext()); - } - return true; -} - -/// Return true if the type should be split out into a type unit. -static bool shouldCreateTypeUnit(DICompositeType CTy, const DwarfDebug *DD) { - uint16_t Tag = CTy.getTag(); - - switch (Tag) { - case dwarf::DW_TAG_structure_type: - case dwarf::DW_TAG_union_type: - case dwarf::DW_TAG_enumeration_type: - case dwarf::DW_TAG_class_type: - // If this is a class, structure, union, or enumeration type - // that is a definition (not a declaration), and not scoped - // inside a function then separate this out as a type unit. - return !CTy.isForwardDecl() && isTypeUnitScoped(CTy, DD); - default: - return false; +/// constructSubprogramArguments - Construct function argument DIEs. +void DwarfUnit::constructSubprogramArguments(DIE &Buffer, DIArray Args) { + for (unsigned i = 1, N = Args.getNumElements(); i < N; ++i) { + DIDescriptor Ty = Args.getElement(i); + if (Ty.isUnspecifiedParameter()) { + assert(i == N-1 && "Unspecified parameter must be the last argument"); + createAndAddDIE(dwarf::DW_TAG_unspecified_parameters, Buffer); + } else { + DIE *Arg = createAndAddDIE(dwarf::DW_TAG_formal_parameter, Buffer); + addType(Arg, DIType(Ty)); + if (DIType(Ty).isArtificial()) + addFlag(Arg, dwarf::DW_AT_artificial); + } } } /// constructTypeDIE - Construct type DIE from DICompositeType. -void CompileUnit::constructTypeDIE(DIE &Buffer, DICompositeType CTy) { - // Get core information. +void DwarfUnit::constructTypeDIE(DIE &Buffer, DICompositeType CTy) { + // Add name if not anonymous or intermediate type. StringRef Name = CTy.getName(); uint64_t Size = CTy.getSizeInBits() >> 3; @@ -1148,19 +1229,12 @@ void CompileUnit::constructTypeDIE(DIE &Buffer, DICompositeType CTy) { addType(&Buffer, RTy); bool isPrototyped = true; - // Add arguments. - for (unsigned i = 1, N = Elements.getNumElements(); i < N; ++i) { - DIDescriptor Ty = Elements.getElement(i); - if (Ty.isUnspecifiedParameter()) { - createAndAddDIE(dwarf::DW_TAG_unspecified_parameters, Buffer); - isPrototyped = false; - } else { - DIE *Arg = createAndAddDIE(dwarf::DW_TAG_formal_parameter, Buffer); - addType(Arg, DIType(Ty)); - if (DIType(Ty).isArtificial()) - addFlag(Arg, dwarf::DW_AT_artificial); - } - } + if (Elements.getNumElements() == 2 && + Elements.getElement(1).isUnspecifiedParameter()) + isPrototyped = false; + + constructSubprogramArguments(Buffer, Elements); + // Add prototype flag if we're dealing with a C language and the // function has been prototyped. uint16_t Language = getLanguage(); @@ -1168,6 +1242,12 @@ void CompileUnit::constructTypeDIE(DIE &Buffer, DICompositeType CTy) { (Language == dwarf::DW_LANG_C89 || Language == dwarf::DW_LANG_C99 || Language == dwarf::DW_LANG_ObjC)) addFlag(&Buffer, dwarf::DW_AT_prototyped); + + if (CTy.isLValueReference()) + addFlag(&Buffer, dwarf::DW_AT_reference); + + if (CTy.isRValueReference()) + addFlag(&Buffer, dwarf::DW_AT_rvalue_reference); } break; case dwarf::DW_TAG_structure_type: case dwarf::DW_TAG_union_type: @@ -1177,21 +1257,9 @@ void CompileUnit::constructTypeDIE(DIE &Buffer, DICompositeType CTy) { for (unsigned i = 0, N = Elements.getNumElements(); i < N; ++i) { DIDescriptor Element = Elements.getElement(i); DIE *ElemDie = NULL; - if (Element.isSubprogram()) { - DISubprogram SP(Element); - ElemDie = getOrCreateSubprogramDIE(SP); - if (SP.isProtected()) - addUInt(ElemDie, dwarf::DW_AT_accessibility, dwarf::DW_FORM_data1, - dwarf::DW_ACCESS_protected); - else if (SP.isPrivate()) - addUInt(ElemDie, dwarf::DW_AT_accessibility, dwarf::DW_FORM_data1, - dwarf::DW_ACCESS_private); - else - addUInt(ElemDie, dwarf::DW_AT_accessibility, dwarf::DW_FORM_data1, - dwarf::DW_ACCESS_public); - if (SP.isExplicit()) - addFlag(ElemDie, dwarf::DW_AT_explicit); - } else if (Element.isDerivedType()) { + if (Element.isSubprogram()) + ElemDie = getOrCreateSubprogramDIE(DISubprogram(Element)); + else if (Element.isDerivedType()) { DIDerivedType DDTy(Element); if (DDTy.getTag() == dwarf::DW_TAG_friend) { ElemDie = createAndAddDIE(dwarf::DW_TAG_friend, Buffer); @@ -1207,7 +1275,8 @@ void CompileUnit::constructTypeDIE(DIE &Buffer, DICompositeType CTy) { ElemDie = createAndAddDIE(Property.getTag(), Buffer); StringRef PropertyName = Property.getObjCPropertyName(); addString(ElemDie, dwarf::DW_AT_APPLE_property_name, PropertyName); - addType(ElemDie, Property.getType()); + if (Property.getType()) + addType(ElemDie, Property.getType()); addSourceLine(ElemDie, Property); StringRef GetterName = Property.getObjCPropertyGetterName(); if (!GetterName.empty()) @@ -1293,17 +1362,12 @@ void CompileUnit::constructTypeDIE(DIE &Buffer, DICompositeType CTy) { addUInt(&Buffer, dwarf::DW_AT_APPLE_runtime_class, dwarf::DW_FORM_data1, RLang); } - // If this is a type applicable to a type unit it then add it to the - // list of types we'll compute a hash for later. - if (shouldCreateTypeUnit(CTy, DD)) - DD->addTypeUnitType(&Buffer); } /// constructTemplateTypeParameterDIE - Construct new DIE for the given /// DITemplateTypeParameter. -void -CompileUnit::constructTemplateTypeParameterDIE(DIE &Buffer, - DITemplateTypeParameter TP) { +void DwarfUnit::constructTemplateTypeParameterDIE(DIE &Buffer, + DITemplateTypeParameter TP) { DIE *ParamDIE = createAndAddDIE(dwarf::DW_TAG_template_type_parameter, Buffer); // Add the type if it exists, it could be void and therefore no type. @@ -1316,8 +1380,8 @@ CompileUnit::constructTemplateTypeParameterDIE(DIE &Buffer, /// constructTemplateValueParameterDIE - Construct new DIE for the given /// DITemplateValueParameter. void -CompileUnit::constructTemplateValueParameterDIE(DIE &Buffer, - DITemplateValueParameter VP) { +DwarfUnit::constructTemplateValueParameterDIE(DIE &Buffer, + DITemplateValueParameter VP) { DIE *ParamDIE = createAndAddDIE(VP.getTag(), Buffer); // Add the type if there is one, template template and template parameter @@ -1333,12 +1397,12 @@ CompileUnit::constructTemplateValueParameterDIE(DIE &Buffer, else if (GlobalValue *GV = dyn_cast<GlobalValue>(Val)) { // For declaration non-type template parameters (such as global values and // functions) - DIEBlock *Block = new (DIEValueAllocator) DIEBlock(); - addOpAddress(Block, Asm->getSymbol(GV)); + DIELoc *Loc = new (DIEValueAllocator) DIELoc(); + addOpAddress(Loc, Asm->getSymbol(GV)); // Emit DW_OP_stack_value to use the address as the immediate value of the // parameter, rather than a pointer to it. - addUInt(Block, dwarf::DW_FORM_data1, dwarf::DW_OP_stack_value); - addBlock(ParamDIE, dwarf::DW_AT_location, Block); + addUInt(Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_stack_value); + addBlock(ParamDIE, dwarf::DW_AT_location, Loc); } else if (VP.getTag() == dwarf::DW_TAG_GNU_template_template_param) { assert(isa<MDString>(Val)); addString(ParamDIE, dwarf::DW_AT_GNU_template_name, @@ -1352,7 +1416,7 @@ CompileUnit::constructTemplateValueParameterDIE(DIE &Buffer, } /// getOrCreateNameSpace - Create a DIE for DINameSpace. -DIE *CompileUnit::getOrCreateNameSpace(DINameSpace NS) { +DIE *DwarfUnit::getOrCreateNameSpace(DINameSpace NS) { // Construct the context before querying for the existence of the DIE in case // such construction creates the DIE. DIE *ContextDIE = getOrCreateContextDIE(NS.getContext()); @@ -1373,11 +1437,16 @@ DIE *CompileUnit::getOrCreateNameSpace(DINameSpace NS) { } /// getOrCreateSubprogramDIE - Create new DIE using SP. -DIE *CompileUnit::getOrCreateSubprogramDIE(DISubprogram SP) { +DIE *DwarfUnit::getOrCreateSubprogramDIE(DISubprogram SP) { // Construct the context before querying for the existence of the DIE in case // such construction creates the DIE (as is the case for member function // declarations). - DIE *ContextDIE = getOrCreateContextDIE(resolve(SP.getContext())); + DIScope Context = resolve(SP.getContext()); + DIE *ContextDIE = getOrCreateContextDIE(Context); + + // Unique declarations based on the ODR, where applicable. + SP = DISubprogram(DD->resolve(SP.getRef())); + assert(SP.Verify()); DIE *SPDie = getDIE(SP); if (SPDie) @@ -1386,7 +1455,7 @@ DIE *CompileUnit::getOrCreateSubprogramDIE(DISubprogram SP) { DISubprogram SPDecl = SP.getFunctionDeclaration(); if (SPDecl.isSubprogram()) // Add subprogram definitions to the CU die directly. - ContextDIE = CUDie.get(); + ContextDIE = UnitDie.get(); // DW_TAG_inlined_subroutine may refer to this DIE. SPDie = createAndAddDIE(dwarf::DW_TAG_subprogram, *ContextDIE, SP); @@ -1440,7 +1509,7 @@ DIE *CompileUnit::getOrCreateSubprogramDIE(DISubprogram SP) { unsigned VK = SP.getVirtuality(); if (VK) { addUInt(SPDie, dwarf::DW_AT_virtuality, dwarf::DW_FORM_data1, VK); - DIEBlock *Block = getDIEBlock(); + DIELoc *Block = getDIELoc(); addUInt(Block, dwarf::DW_FORM_data1, dwarf::DW_OP_constu); addUInt(Block, dwarf::DW_FORM_udata, SP.getVirtualIndex()); addBlock(SPDie, dwarf::DW_AT_vtable_elem_location, Block); @@ -1453,13 +1522,7 @@ DIE *CompileUnit::getOrCreateSubprogramDIE(DISubprogram SP) { // Add arguments. Do not add arguments for subprogram definition. They will // be handled while processing variables. - for (unsigned i = 1, N = Args.getNumElements(); i < N; ++i) { - DIE *Arg = createAndAddDIE(dwarf::DW_TAG_formal_parameter, *SPDie); - DIType ATy(Args.getElement(i)); - addType(Arg, ATy); - if (ATy.isArtificial()) - addFlag(Arg, dwarf::DW_AT_artificial); - } + constructSubprogramArguments(*SPDie, Args); } if (SP.isArtificial()) @@ -1475,6 +1538,25 @@ DIE *CompileUnit::getOrCreateSubprogramDIE(DISubprogram SP) { addUInt(SPDie, dwarf::DW_AT_APPLE_isa, dwarf::DW_FORM_flag, isa); } + if (SP.isLValueReference()) + addFlag(SPDie, dwarf::DW_AT_reference); + + if (SP.isRValueReference()) + addFlag(SPDie, dwarf::DW_AT_rvalue_reference); + + if (SP.isProtected()) + addUInt(SPDie, dwarf::DW_AT_accessibility, dwarf::DW_FORM_data1, + dwarf::DW_ACCESS_protected); + else if (SP.isPrivate()) + addUInt(SPDie, dwarf::DW_AT_accessibility, dwarf::DW_FORM_data1, + dwarf::DW_ACCESS_private); + else + addUInt(SPDie, dwarf::DW_AT_accessibility, dwarf::DW_FORM_data1, + dwarf::DW_ACCESS_public); + + if (SP.isExplicit()) + addFlag(SPDie, dwarf::DW_AT_explicit); + return SPDie; } @@ -1506,17 +1588,15 @@ static const ConstantExpr *getMergedGlobalExpr(const Value *V) { } /// createGlobalVariableDIE - create global variable DIE. -void CompileUnit::createGlobalVariableDIE(DIGlobalVariable GV) { - +void DwarfCompileUnit::createGlobalVariableDIE(DIGlobalVariable GV) { // Check for pre-existence. if (getDIE(GV)) return; - if (!GV.isGlobalVariable()) - return; + assert(GV.isGlobalVariable()); DIScope GVContext = GV.getContext(); - DIType GTy = GV.getType(); + DIType GTy = DD->resolve(GV.getType()); // If this is a static data member definition, some attributes belong // to the declaration DIE. @@ -1558,44 +1638,46 @@ void CompileUnit::createGlobalVariableDIE(DIGlobalVariable GV) { bool isGlobalVariable = GV.getGlobal() != NULL; if (isGlobalVariable) { addToAccelTable = true; - DIEBlock *Block = new (DIEValueAllocator) DIEBlock(); + DIELoc *Loc = new (DIEValueAllocator) DIELoc(); const MCSymbol *Sym = Asm->getSymbol(GV.getGlobal()); if (GV.getGlobal()->isThreadLocal()) { // FIXME: Make this work with -gsplit-dwarf. unsigned PointerSize = Asm->getDataLayout().getPointerSize(); assert((PointerSize == 4 || PointerSize == 8) && "Add support for other sizes if necessary"); - const MCExpr *Expr = - Asm->getObjFileLowering().getDebugThreadLocalSymbol(Sym); // Based on GCC's support for TLS: if (!DD->useSplitDwarf()) { // 1) Start with a constNu of the appropriate pointer size - addUInt(Block, dwarf::DW_FORM_data1, + addUInt(Loc, dwarf::DW_FORM_data1, PointerSize == 4 ? dwarf::DW_OP_const4u : dwarf::DW_OP_const8u); // 2) containing the (relocated) offset of the TLS variable // within the module's TLS block. - addExpr(Block, dwarf::DW_FORM_udata, Expr); + addExpr(Loc, dwarf::DW_FORM_udata, + Asm->getObjFileLowering().getDebugThreadLocalSymbol(Sym)); } else { - addUInt(Block, dwarf::DW_FORM_data1, dwarf::DW_OP_GNU_const_index); - addUInt(Block, dwarf::DW_FORM_udata, DU->getAddrPoolIndex(Expr)); + addUInt(Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_GNU_const_index); + addUInt(Loc, dwarf::DW_FORM_udata, + DU->getAddrPoolIndex(Sym, /* TLS */ true)); } // 3) followed by a custom OP to make the debugger do a TLS lookup. - addUInt(Block, dwarf::DW_FORM_data1, dwarf::DW_OP_GNU_push_tls_address); - } else - addOpAddress(Block, Sym); + addUInt(Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_GNU_push_tls_address); + } else { + DD->addArangeLabel(SymbolCU(this, Sym)); + addOpAddress(Loc, Sym); + } // Do not create specification DIE if context is either compile unit // or a subprogram. if (GVContext && GV.isDefinition() && !GVContext.isCompileUnit() && !GVContext.isFile() && !DD->isSubprogramContext(GVContext)) { // Create specification DIE. - VariableSpecDIE = createAndAddDIE(dwarf::DW_TAG_variable, *CUDie); + VariableSpecDIE = createAndAddDIE(dwarf::DW_TAG_variable, *UnitDie); addDIEEntry(VariableSpecDIE, dwarf::DW_AT_specification, VariableDIE); - addBlock(VariableSpecDIE, dwarf::DW_AT_location, Block); + addBlock(VariableSpecDIE, dwarf::DW_AT_location, Loc); // A static member's declaration is already flagged as such. if (!SDMDecl.Verify()) addFlag(VariableDIE, dwarf::DW_AT_declaration); } else { - addBlock(VariableDIE, dwarf::DW_AT_location, Block); + addBlock(VariableDIE, dwarf::DW_AT_location, Loc); } // Add the linkage name. StringRef LinkageName = GV.getLinkageName(); @@ -1605,7 +1687,8 @@ void CompileUnit::createGlobalVariableDIE(DIGlobalVariable GV) { // TAG_variable. addString(IsStaticMember && VariableSpecDIE ? VariableSpecDIE : VariableDIE, - dwarf::DW_AT_MIPS_linkage_name, + DD->getDwarfVersion() >= 4 ? dwarf::DW_AT_linkage_name + : dwarf::DW_AT_MIPS_linkage_name, GlobalValue::getRealLinkageName(LinkageName)); } else if (const ConstantInt *CI = dyn_cast_or_null<ConstantInt>(GV.getConstant())) { @@ -1617,15 +1700,17 @@ void CompileUnit::createGlobalVariableDIE(DIGlobalVariable GV) { } else if (const ConstantExpr *CE = getMergedGlobalExpr(GV->getOperand(11))) { addToAccelTable = true; // GV is a merged global. - DIEBlock *Block = new (DIEValueAllocator) DIEBlock(); + DIELoc *Loc = new (DIEValueAllocator) DIELoc(); Value *Ptr = CE->getOperand(0); - addOpAddress(Block, Asm->getSymbol(cast<GlobalValue>(Ptr))); - addUInt(Block, dwarf::DW_FORM_data1, dwarf::DW_OP_constu); + MCSymbol *Sym = Asm->getSymbol(cast<GlobalValue>(Ptr)); + DD->addArangeLabel(SymbolCU(this, Sym)); + addOpAddress(Loc, Sym); + addUInt(Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_constu); SmallVector<Value *, 3> Idx(CE->op_begin() + 1, CE->op_end()); - addUInt(Block, dwarf::DW_FORM_udata, + addUInt(Loc, dwarf::DW_FORM_udata, Asm->getDataLayout().getIndexedOffset(Ptr->getType(), Idx)); - addUInt(Block, dwarf::DW_FORM_data1, dwarf::DW_OP_plus); - addBlock(VariableDIE, dwarf::DW_AT_location, Block); + addUInt(Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_plus); + addBlock(VariableDIE, dwarf::DW_AT_location, Loc); } if (addToAccelTable) { @@ -1644,8 +1729,7 @@ void CompileUnit::createGlobalVariableDIE(DIGlobalVariable GV) { } /// constructSubrangeDIE - Construct subrange DIE from DISubrange. -void CompileUnit::constructSubrangeDIE(DIE &Buffer, DISubrange SR, - DIE *IndexTy) { +void DwarfUnit::constructSubrangeDIE(DIE &Buffer, DISubrange SR, DIE *IndexTy) { DIE *DW_Subrange = createAndAddDIE(dwarf::DW_TAG_subrange_type, Buffer); addDIEEntry(DW_Subrange, dwarf::DW_AT_type, IndexTy); @@ -1670,7 +1754,7 @@ void CompileUnit::constructSubrangeDIE(DIE &Buffer, DISubrange SR, } /// constructArrayTypeDIE - Construct array type DIE from DICompositeType. -void CompileUnit::constructArrayTypeDIE(DIE &Buffer, DICompositeType CTy) { +void DwarfUnit::constructArrayTypeDIE(DIE &Buffer, DICompositeType CTy) { if (CTy.isVector()) addFlag(&Buffer, dwarf::DW_AT_GNU_vector); @@ -1682,12 +1766,12 @@ void CompileUnit::constructArrayTypeDIE(DIE &Buffer, DICompositeType CTy) { // as different languages may have different sizes for indexes. DIE *IdxTy = getIndexTyDie(); if (!IdxTy) { - // Construct an anonymous type for index type. - IdxTy = createAndAddDIE(dwarf::DW_TAG_base_type, *CUDie.get()); - addString(IdxTy, dwarf::DW_AT_name, "int"); - addUInt(IdxTy, dwarf::DW_AT_byte_size, None, sizeof(int32_t)); + // Construct an integer type to use for indexes. + IdxTy = createAndAddDIE(dwarf::DW_TAG_base_type, *UnitDie); + addString(IdxTy, dwarf::DW_AT_name, "sizetype"); + addUInt(IdxTy, dwarf::DW_AT_byte_size, None, sizeof(int64_t)); addUInt(IdxTy, dwarf::DW_AT_encoding, dwarf::DW_FORM_data1, - dwarf::DW_ATE_signed); + dwarf::DW_ATE_unsigned); setIndexTyDie(IdxTy); } @@ -1701,7 +1785,7 @@ void CompileUnit::constructArrayTypeDIE(DIE &Buffer, DICompositeType CTy) { } /// constructEnumTypeDIE - Construct an enum type DIE from DICompositeType. -void CompileUnit::constructEnumTypeDIE(DIE &Buffer, DICompositeType CTy) { +void DwarfUnit::constructEnumTypeDIE(DIE &Buffer, DICompositeType CTy) { DIArray Elements = CTy.getTypeArray(); // Add enumerators to enumeration type. @@ -1712,7 +1796,8 @@ void CompileUnit::constructEnumTypeDIE(DIE &Buffer, DICompositeType CTy) { StringRef Name = Enum.getName(); addString(Enumerator, dwarf::DW_AT_name, Name); int64_t Value = Enum.getEnumValue(); - addSInt(Enumerator, dwarf::DW_AT_const_value, dwarf::DW_FORM_sdata, Value); + addSInt(Enumerator, dwarf::DW_AT_const_value, dwarf::DW_FORM_sdata, + Value); } } DIType DTy = resolve(CTy.getTypeDerivedFrom()); @@ -1724,7 +1809,7 @@ void CompileUnit::constructEnumTypeDIE(DIE &Buffer, DICompositeType CTy) { /// constructContainingTypeDIEs - Construct DIEs for types that contain /// vtables. -void CompileUnit::constructContainingTypeDIEs() { +void DwarfUnit::constructContainingTypeDIEs() { for (DenseMap<DIE *, const MDNode *>::iterator CI = ContainingTypeMap.begin(), CE = ContainingTypeMap.end(); CI != CE; ++CI) { @@ -1740,7 +1825,7 @@ void CompileUnit::constructContainingTypeDIEs() { } /// constructVariableDIE - Construct a DIE for the given DbgVariable. -DIE *CompileUnit::constructVariableDIE(DbgVariable &DV, bool isScopeAbstract) { +DIE *DwarfUnit::constructVariableDIE(DbgVariable &DV, bool isScopeAbstract) { StringRef Name = DV.getName(); // Define variable debug information entry. @@ -1768,10 +1853,7 @@ DIE *CompileUnit::constructVariableDIE(DbgVariable &DV, bool isScopeAbstract) { unsigned Offset = DV.getDotDebugLocOffset(); if (Offset != ~0U) { - addLabel(VariableDie, dwarf::DW_AT_location, - DD->getDwarfVersion() >= 4 ? dwarf::DW_FORM_sec_offset - : dwarf::DW_FORM_data4, - Asm->GetTempSymbol("debug_loc", Offset)); + addLocationList(VariableDie, dwarf::DW_AT_location, Offset); DV.setDIE(VariableDie); return VariableDie; } @@ -1815,7 +1897,7 @@ DIE *CompileUnit::constructVariableDIE(DbgVariable &DV, bool isScopeAbstract) { } /// constructMemberDIE - Construct member DIE from DIDerivedType. -void CompileUnit::constructMemberDIE(DIE &Buffer, DIDerivedType DT) { +void DwarfUnit::constructMemberDIE(DIE &Buffer, DIDerivedType DT) { DIE *MemberDie = createAndAddDIE(DT.getTag(), Buffer); StringRef Name = DT.getName(); if (!Name.empty()) @@ -1825,16 +1907,13 @@ void CompileUnit::constructMemberDIE(DIE &Buffer, DIDerivedType DT) { addSourceLine(MemberDie, DT); - DIEBlock *MemLocationDie = new (DIEValueAllocator) DIEBlock(); - addUInt(MemLocationDie, dwarf::DW_FORM_data1, dwarf::DW_OP_plus_uconst); - if (DT.getTag() == dwarf::DW_TAG_inheritance && DT.isVirtual()) { // For C++, virtual base classes are not at fixed offset. Use following // expression to extract appropriate offset from vtable. // BaseAddr = ObAddr + *((*ObAddr) - Offset) - DIEBlock *VBaseLocationDie = new (DIEValueAllocator) DIEBlock(); + DIELoc *VBaseLocationDie = new (DIEValueAllocator) DIELoc(); addUInt(VBaseLocationDie, dwarf::DW_FORM_data1, dwarf::DW_OP_dup); addUInt(VBaseLocationDie, dwarf::DW_FORM_data1, dwarf::DW_OP_deref); addUInt(VBaseLocationDie, dwarf::DW_FORM_data1, dwarf::DW_OP_constu); @@ -1850,10 +1929,9 @@ void CompileUnit::constructMemberDIE(DIE &Buffer, DIDerivedType DT) { uint64_t OffsetInBytes; if (Size != FieldSize) { - // Handle bitfield. - addUInt(MemberDie, dwarf::DW_AT_byte_size, None, - getBaseTypeSize(DD, DT) >> 3); - addUInt(MemberDie, dwarf::DW_AT_bit_size, None, DT.getSizeInBits()); + // Handle bitfield, assume bytes are 8 bits. + addUInt(MemberDie, dwarf::DW_AT_byte_size, None, FieldSize/8); + addUInt(MemberDie, dwarf::DW_AT_bit_size, None, Size); uint64_t Offset = DT.getOffsetInBits(); uint64_t AlignMask = ~(DT.getAlignInBits() - 1); @@ -1866,13 +1944,21 @@ void CompileUnit::constructMemberDIE(DIE &Buffer, DIDerivedType DT) { Offset = FieldSize - (Offset + Size); addUInt(MemberDie, dwarf::DW_AT_bit_offset, None, Offset); - // Here WD_AT_data_member_location points to the anonymous + // Here DW_AT_data_member_location points to the anonymous // field that includes this bit field. OffsetInBytes = FieldOffset >> 3; } else // This is not a bitfield. OffsetInBytes = DT.getOffsetInBits() >> 3; - addUInt(MemberDie, dwarf::DW_AT_data_member_location, None, OffsetInBytes); + + if (DD->getDwarfVersion() <= 2) { + DIELoc *MemLocationDie = new (DIEValueAllocator) DIELoc(); + addUInt(MemLocationDie, dwarf::DW_FORM_data1, dwarf::DW_OP_plus_uconst); + addUInt(MemLocationDie, dwarf::DW_FORM_udata, OffsetInBytes); + addBlock(MemberDie, dwarf::DW_AT_data_member_location, MemLocationDie); + } else + addUInt(MemberDie, dwarf::DW_AT_data_member_location, None, + OffsetInBytes); } if (DT.isProtected()) @@ -1900,7 +1986,7 @@ void CompileUnit::constructMemberDIE(DIE &Buffer, DIDerivedType DT) { } /// getOrCreateStaticMemberDIE - Create new DIE for C++ static member. -DIE *CompileUnit::getOrCreateStaticMemberDIE(DIDerivedType DT) { +DIE *DwarfUnit::getOrCreateStaticMemberDIE(DIDerivedType DT) { if (!DT.Verify()) return NULL; @@ -1944,13 +2030,89 @@ DIE *CompileUnit::getOrCreateStaticMemberDIE(DIDerivedType DT) { return StaticMemberDIE; } -void CompileUnit::emitHeader(const MCSection *ASection, - const MCSymbol *ASectionSym) { +void DwarfUnit::emitHeader(const MCSymbol *ASectionSym) const { Asm->OutStreamer.AddComment("DWARF version number"); Asm->EmitInt16(DD->getDwarfVersion()); Asm->OutStreamer.AddComment("Offset Into Abbrev. Section"); - Asm->EmitSectionOffset(Asm->GetTempSymbol(ASection->getLabelBeginName()), - ASectionSym); + // We share one abbreviations table across all units so it's always at the + // start of the section. Use a relocatable offset where needed to ensure + // linking doesn't invalidate that offset. + if (ASectionSym) + Asm->EmitSectionOffset(ASectionSym, ASectionSym); + else + // Use a constant value when no symbol is provided. + Asm->EmitInt32(0); Asm->OutStreamer.AddComment("Address Size (in bytes)"); Asm->EmitInt8(Asm->getDataLayout().getPointerSize()); } + +void DwarfUnit::addRange(RangeSpan Range) { + // Only add a range for this unit if we're emitting full debug. + if (getCUNode().getEmissionKind() == DIBuilder::FullDebug) { + // If we have no current ranges just add the range and return, otherwise, + // check the current section and CU against the previous section and CU we + // emitted into and the subprogram was contained within. If these are the + // same then extend our current range, otherwise add this as a new range. + if (CURanges.size() == 0 || + this != DD->getPrevCU() || + Asm->getCurrentSection() != DD->getPrevSection()) { + CURanges.push_back(Range); + return; + } + + assert(&(CURanges.back().getEnd()->getSection()) == + &(Range.getEnd()->getSection()) && + "We can only append to a range in the same section!"); + CURanges.back().setEnd(Range.getEnd()); + } +} + +void DwarfCompileUnit::initStmtList(MCSymbol *DwarfLineSectionSym) { + // Define start line table label for each Compile Unit. + MCSymbol *LineTableStartSym = + Asm->OutStreamer.getDwarfLineTableSymbol(getUniqueID()); + + stmtListIndex = UnitDie->getValues().size(); + + // DW_AT_stmt_list is a offset of line number information for this + // compile unit in debug_line section. For split dwarf this is + // left in the skeleton CU and so not included. + // The line table entries are not always emitted in assembly, so it + // is not okay to use line_table_start here. + if (Asm->MAI->doesDwarfUseRelocationsAcrossSections()) + addSectionLabel(UnitDie.get(), dwarf::DW_AT_stmt_list, LineTableStartSym); + else + addSectionDelta(UnitDie.get(), dwarf::DW_AT_stmt_list, LineTableStartSym, + DwarfLineSectionSym); +} + +void DwarfCompileUnit::applyStmtList(DIE &D) { + D.addValue(dwarf::DW_AT_stmt_list, + UnitDie->getAbbrev().getData()[stmtListIndex].getForm(), + UnitDie->getValues()[stmtListIndex]); +} + +void DwarfTypeUnit::emitHeader(const MCSymbol *ASectionSym) const { + DwarfUnit::emitHeader(ASectionSym); + Asm->OutStreamer.AddComment("Type Signature"); + Asm->OutStreamer.EmitIntValue(TypeSignature, sizeof(TypeSignature)); + Asm->OutStreamer.AddComment("Type DIE Offset"); + // In a skeleton type unit there is no type DIE so emit a zero offset. + Asm->OutStreamer.EmitIntValue(Ty ? Ty->getOffset() : 0, + sizeof(Ty->getOffset())); +} + +void DwarfTypeUnit::initSection(const MCSection *Section) { + assert(!this->Section); + this->Section = Section; + // Since each type unit is contained in its own COMDAT section, the begin + // label and the section label are the same. Using the begin label emission in + // DwarfDebug to emit the section label as well is slightly subtle/sneaky, but + // the only other alternative of lazily constructing start-of-section labels + // and storing a mapping in DwarfDebug (or AsmPrinter). + this->SectionSym = this->LabelBegin = + Asm->GetTempSymbol(Section->getLabelBeginName(), getUniqueID()); + this->LabelEnd = + Asm->GetTempSymbol(Section->getLabelEndName(), getUniqueID()); + this->LabelRange = Asm->GetTempSymbol("gnu_ranges", getUniqueID()); +} diff --git a/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h b/lib/CodeGen/AsmPrinter/DwarfUnit.h index d782c88a51..ef713f7cf0 100644 --- a/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h +++ b/lib/CodeGen/AsmPrinter/DwarfUnit.h @@ -1,4 +1,4 @@ -//===-- llvm/CodeGen/DwarfCompileUnit.h - Dwarf Compile Unit ---*- C++ -*--===// +//===-- llvm/CodeGen/DwarfUnit.h - Dwarf Compile Unit ---*- C++ -*--===// // // The LLVM Compiler Infrastructure // @@ -18,10 +18,13 @@ #include "DwarfDebug.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/Optional.h" -#include "llvm/ADT/OwningPtr.h" #include "llvm/ADT/StringMap.h" -#include "llvm/DebugInfo.h" +#include "llvm/CodeGen/AsmPrinter.h" +#include "llvm/IR/DIBuilder.h" +#include "llvm/IR/DebugInfo.h" #include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCSection.h" +#include "llvm/MC/MCDwarf.h" namespace llvm { @@ -30,30 +33,59 @@ class MachineOperand; class ConstantInt; class ConstantFP; class DbgVariable; +class DwarfCompileUnit; + +// Data structure to hold a range for range lists. +class RangeSpan { +public: + RangeSpan(MCSymbol *S, MCSymbol *E) : Start(S), End(E) {} + const MCSymbol *getStart() const { return Start; } + const MCSymbol *getEnd() const { return End; } + void setEnd(const MCSymbol *E) { End = E; } + +private: + const MCSymbol *Start, *End; +}; + +class RangeSpanList { +private: + // Index for locating within the debug_range section this particular span. + MCSymbol *RangeSym; + // List of ranges. + SmallVector<RangeSpan, 2> Ranges; + +public: + RangeSpanList(MCSymbol *Sym) : RangeSym(Sym) {} + MCSymbol *getSym() const { return RangeSym; } + const SmallVectorImpl<RangeSpan> &getRanges() const { return Ranges; } + void addRange(RangeSpan Range) { Ranges.push_back(Range); } +}; //===----------------------------------------------------------------------===// -/// CompileUnit - This dwarf writer support class manages information associated +/// Unit - This dwarf writer support class manages information associated /// with a source file. -class CompileUnit { +class DwarfUnit { +protected: /// UniqueID - a numeric ID unique among all CUs in the module - /// unsigned UniqueID; /// Node - MDNode for the compile unit. - DICompileUnit Node; + DICompileUnit CUNode; - /// CUDie - Compile unit debug information entry. - /// - const OwningPtr<DIE> CUDie; + /// Unit debug information entry. + const std::unique_ptr<DIE> UnitDie; + + /// Offset of the UnitDie from beginning of debug info section. + unsigned DebugInfoOffset; /// Asm - Target of Dwarf emission. AsmPrinter *Asm; // Holders for some common dwarf information. DwarfDebug *DD; - DwarfUnits *DU; + DwarfFile *DU; - /// IndexTyDie - An anonymous type for index type. Owned by CUDie. + /// IndexTyDie - An anonymous type for index type. Owned by UnitDie. DIE *IndexTyDie; /// MDNodeToDieMap - Tracks the mapping of unit level debug information @@ -65,57 +97,150 @@ class CompileUnit { DenseMap<const MDNode *, DIEEntry *> MDNodeToDIEEntryMap; /// GlobalNames - A map of globally visible named entities for this unit. - /// - StringMap<DIE *> GlobalNames; + StringMap<const DIE *> GlobalNames; /// GlobalTypes - A map of globally visible types for this unit. - /// - StringMap<DIE *> GlobalTypes; + StringMap<const DIE *> GlobalTypes; /// AccelNames - A map of names for the name accelerator table. - /// - StringMap<std::vector<DIE *> > AccelNames; - StringMap<std::vector<DIE *> > AccelObjC; - StringMap<std::vector<DIE *> > AccelNamespace; - StringMap<std::vector<std::pair<DIE *, unsigned> > > AccelTypes; + StringMap<std::vector<const DIE *> > AccelNames; + + /// AccelObjC - A map of objc spec for the objc accelerator table. + StringMap<std::vector<const DIE *> > AccelObjC; + + /// AccelNamespace - A map of names for the namespace accelerator table. + StringMap<std::vector<const DIE *> > AccelNamespace; + + /// AccelTypes - A map of names for the type accelerator table. + StringMap<std::vector<std::pair<const DIE *, unsigned> > > AccelTypes; /// DIEBlocks - A list of all the DIEBlocks in use. std::vector<DIEBlock *> DIEBlocks; + + /// DIELocs - A list of all the DIELocs in use. + std::vector<DIELoc *> DIELocs; /// ContainingTypeMap - This map is used to keep track of subprogram DIEs that /// need DW_AT_containing_type attribute. This attribute points to a DIE that /// corresponds to the MDNode mapped with the subprogram DIE. DenseMap<DIE *, const MDNode *> ContainingTypeMap; + // List of ranges for a given compile unit. + SmallVector<RangeSpan, 1> CURanges; + + // List of range lists for a given compile unit, separate from the ranges for + // the CU itself. + SmallVector<RangeSpanList, 1> CURangeLists; + // DIEValueAllocator - All DIEValues are allocated through this allocator. BumpPtrAllocator DIEValueAllocator; // DIEIntegerOne - A preallocated DIEValue because 1 is used frequently. DIEInteger *DIEIntegerOne; + /// The section this unit will be emitted in. + const MCSection *Section; + + /// A label at the start of the non-dwo section related to this unit. + MCSymbol *SectionSym; + + /// The start of the unit within its section. + MCSymbol *LabelBegin; + + /// The end of the unit within its section. + MCSymbol *LabelEnd; + + /// The label for the start of the range sets for the elements of this unit. + MCSymbol *LabelRange; + + /// Skeleton unit associated with this unit. + DwarfUnit *Skeleton; + + DwarfUnit(unsigned UID, DIE *D, DICompileUnit CU, AsmPrinter *A, + DwarfDebug *DW, DwarfFile *DWU); + public: - CompileUnit(unsigned UID, DIE *D, DICompileUnit CU, AsmPrinter *A, - DwarfDebug *DW, DwarfUnits *DWU); - ~CompileUnit(); + virtual ~DwarfUnit(); + + /// Set the skeleton unit associated with this unit. + void setSkeleton(DwarfUnit *Skel) { Skeleton = Skel; } + + /// Get the skeleton unit associated with this unit. + DwarfUnit *getSkeleton() const { return Skeleton; } + + /// Pass in the SectionSym even though we could recreate it in every compile + /// unit (type units will have actually distinct symbols once they're in + /// comdat sections). + void initSection(const MCSection *Section, MCSymbol *SectionSym) { + assert(!this->Section); + this->Section = Section; + this->SectionSym = SectionSym; + this->LabelBegin = + Asm->GetTempSymbol(Section->getLabelBeginName(), getUniqueID()); + this->LabelEnd = + Asm->GetTempSymbol(Section->getLabelEndName(), getUniqueID()); + this->LabelRange = Asm->GetTempSymbol("gnu_ranges", getUniqueID()); + } + + const MCSection *getSection() const { + assert(Section); + return Section; + } + + /// If there's a skeleton then return the section symbol for the skeleton + /// unit, otherwise return the section symbol for this unit. + MCSymbol *getLocalSectionSym() const { + if (Skeleton) + return Skeleton->getSectionSym(); + return getSectionSym(); + } + + MCSymbol *getSectionSym() const { + assert(Section); + return SectionSym; + } + + /// If there's a skeleton then return the begin label for the skeleton unit, + /// otherwise return the local label for this unit. + MCSymbol *getLocalLabelBegin() const { + if (Skeleton) + return Skeleton->getLabelBegin(); + return getLabelBegin(); + } + + MCSymbol *getLabelBegin() const { + assert(Section); + return LabelBegin; + } + + MCSymbol *getLabelEnd() const { + assert(Section); + return LabelEnd; + } + + MCSymbol *getLabelRange() const { + assert(Section); + return LabelRange; + } // Accessors. unsigned getUniqueID() const { return UniqueID; } - uint16_t getLanguage() const { return Node.getLanguage(); } - DICompileUnit getNode() const { return Node; } - DIE *getCUDie() const { return CUDie.get(); } - const StringMap<DIE *> &getGlobalNames() const { return GlobalNames; } - const StringMap<DIE *> &getGlobalTypes() const { return GlobalTypes; } + uint16_t getLanguage() const { return CUNode.getLanguage(); } + DICompileUnit getCUNode() const { return CUNode; } + DIE *getUnitDie() const { return UnitDie.get(); } + const StringMap<const DIE *> &getGlobalNames() const { return GlobalNames; } + const StringMap<const DIE *> &getGlobalTypes() const { return GlobalTypes; } - const StringMap<std::vector<DIE *> > &getAccelNames() const { + const StringMap<std::vector<const DIE *> > &getAccelNames() const { return AccelNames; } - const StringMap<std::vector<DIE *> > &getAccelObjC() const { + const StringMap<std::vector<const DIE *> > &getAccelObjC() const { return AccelObjC; } - const StringMap<std::vector<DIE *> > &getAccelNamespace() const { + const StringMap<std::vector<const DIE *> > &getAccelNamespace() const { return AccelNamespace; } - const StringMap<std::vector<std::pair<DIE *, unsigned> > > & + const StringMap<std::vector<std::pair<const DIE *, unsigned> > > & getAccelTypes() const { return AccelTypes; } @@ -124,8 +249,23 @@ public: void setDebugInfoOffset(unsigned DbgInfoOff) { DebugInfoOffset = DbgInfoOff; } /// hasContent - Return true if this compile unit has something to write out. - /// - bool hasContent() const { return !CUDie->getChildren().empty(); } + bool hasContent() const { return !UnitDie->getChildren().empty(); } + + /// addRange - Add an address range to the list of ranges for this unit. + void addRange(RangeSpan Range); + + /// getRanges - Get the list of ranges for this unit. + const SmallVectorImpl<RangeSpan> &getRanges() const { return CURanges; } + SmallVectorImpl<RangeSpan> &getRanges() { return CURanges; } + + /// addRangeList - Add an address range list to the list of range lists. + void addRangeList(RangeSpanList Ranges) { CURangeLists.push_back(Ranges); } + + /// getRangeLists - Get the vector of range lists. + const SmallVectorImpl<RangeSpanList> &getRangeLists() const { + return CURangeLists; + } + SmallVectorImpl<RangeSpanList> &getRangeLists() { return CURangeLists; } /// getParentContextString - Get a string containing the language specific /// context for a global name. @@ -135,24 +275,17 @@ public: /// void addGlobalName(StringRef Name, DIE *Die, DIScope Context); - /// addGlobalType - Add a new global type to the compile unit. - /// - void addGlobalType(DIType Ty); - - /// addPubTypes - Add a set of types from the subprogram to the global types. - void addPubTypes(DISubprogram SP); - /// addAccelName - Add a new name to the name accelerator table. - void addAccelName(StringRef Name, DIE *Die); + void addAccelName(StringRef Name, const DIE *Die); /// addAccelObjC - Add a new name to the ObjC accelerator table. - void addAccelObjC(StringRef Name, DIE *Die); + void addAccelObjC(StringRef Name, const DIE *Die); /// addAccelNamespace - Add a new name to the namespace accelerator table. - void addAccelNamespace(StringRef Name, DIE *Die); + void addAccelNamespace(StringRef Name, const DIE *Die); /// addAccelType - Add a new type to the type accelerator table. - void addAccelType(StringRef Name, std::pair<DIE *, unsigned> Die); + void addAccelType(StringRef Name, std::pair<const DIE *, unsigned> Die); /// getDIE - Returns the debug information entry map slot for the /// specified debug variable. We delegate the request to DwarfDebug @@ -161,7 +294,8 @@ public: /// kept in DwarfDebug. DIE *getDIE(DIDescriptor D) const; - DIEBlock *getDIEBlock() { return new (DIEValueAllocator) DIEBlock(); } + /// getDIELoc - Returns a fresh newly allocated DIELoc. + DIELoc *getDIELoc() { return new (DIEValueAllocator) DIELoc(); } /// insertDIE - Insert DIE into the map. We delegate the request to DwarfDebug /// when the MDNode can be part of the type system, since DIEs for @@ -171,73 +305,81 @@ public: /// addDie - Adds or interns the DIE to the compile unit. /// - void addDie(DIE *Buffer) { CUDie->addChild(Buffer); } + void addDie(DIE *Buffer) { UnitDie->addChild(Buffer); } /// addFlag - Add a flag that is true to the DIE. void addFlag(DIE *Die, dwarf::Attribute Attribute); /// addUInt - Add an unsigned integer attribute data and value. - /// void addUInt(DIE *Die, dwarf::Attribute Attribute, Optional<dwarf::Form> Form, uint64_t Integer); - void addUInt(DIEBlock *Block, dwarf::Form Form, uint64_t Integer); + void addUInt(DIE *Block, dwarf::Form Form, uint64_t Integer); /// addSInt - Add an signed integer attribute data and value. - /// void addSInt(DIE *Die, dwarf::Attribute Attribute, Optional<dwarf::Form> Form, int64_t Integer); - void addSInt(DIEBlock *Die, Optional<dwarf::Form> Form, int64_t Integer); + void addSInt(DIELoc *Die, Optional<dwarf::Form> Form, int64_t Integer); /// addString - Add a string attribute data and value. - /// void addString(DIE *Die, dwarf::Attribute Attribute, const StringRef Str); /// addLocalString - Add a string attribute data and value. - /// - void addLocalString(DIE *Die, dwarf::Attribute Attribute, const StringRef Str); + void addLocalString(DIE *Die, dwarf::Attribute Attribute, + const StringRef Str); /// addExpr - Add a Dwarf expression attribute data and value. - /// - void addExpr(DIEBlock *Die, dwarf::Form Form, const MCExpr *Expr); + void addExpr(DIELoc *Die, dwarf::Form Form, const MCExpr *Expr); /// addLabel - Add a Dwarf label attribute data and value. - /// void addLabel(DIE *Die, dwarf::Attribute Attribute, dwarf::Form Form, const MCSymbol *Label); - void addLabel(DIEBlock *Die, dwarf::Form Form, const MCSymbol *Label); + void addLabel(DIELoc *Die, dwarf::Form Form, const MCSymbol *Label); - /// addLabelAddress - Add a dwarf label attribute data and value using - /// either DW_FORM_addr or DW_FORM_GNU_addr_index. + /// addLocationList - Add a Dwarf loclistptr attribute data and value. + void addLocationList(DIE *Die, dwarf::Attribute Attribute, unsigned Index); + + /// addSectionLabel - Add a Dwarf section label attribute data and value. /// - void addLabelAddress(DIE *Die, dwarf::Attribute Attribute, MCSymbol *Label); + void addSectionLabel(DIE *Die, dwarf::Attribute Attribute, + const MCSymbol *Label); + + /// addSectionOffset - Add an offset into a section attribute data and value. + /// + void addSectionOffset(DIE *Die, dwarf::Attribute Attribute, uint64_t Integer); /// addOpAddress - Add a dwarf op address data and value using the /// form given and an op of either DW_FORM_addr or DW_FORM_GNU_addr_index. - /// - void addOpAddress(DIEBlock *Die, const MCSymbol *Label); + void addOpAddress(DIELoc *Die, const MCSymbol *Label); - /// addDelta - Add a label delta attribute data and value. - /// - void addDelta(DIE *Die, dwarf::Attribute Attribute, dwarf::Form Form, const MCSymbol *Hi, - const MCSymbol *Lo); + /// addSectionDelta - Add a label delta attribute data and value. + void addSectionDelta(DIE *Die, dwarf::Attribute Attribute, const MCSymbol *Hi, + const MCSymbol *Lo); + + /// addLabelDelta - Add a label delta attribute data and value. + void addLabelDelta(DIE *Die, dwarf::Attribute Attribute, const MCSymbol *Hi, + const MCSymbol *Lo); /// addDIEEntry - Add a DIE attribute data and value. - /// void addDIEEntry(DIE *Die, dwarf::Attribute Attribute, DIE *Entry); /// addDIEEntry - Add a DIE attribute data and value. - /// void addDIEEntry(DIE *Die, dwarf::Attribute Attribute, DIEEntry *Entry); + void addDIETypeSignature(DIE *Die, const DwarfTypeUnit &Type); + + /// addBlock - Add block data. + void addBlock(DIE *Die, dwarf::Attribute Attribute, DIELoc *Block); + /// addBlock - Add block data. - /// void addBlock(DIE *Die, dwarf::Attribute Attribute, DIEBlock *Block); /// addSourceLine - Add location information to specified debug information /// entry. + void addSourceLine(DIE *Die, unsigned Line, StringRef File, + StringRef Directory); void addSourceLine(DIE *Die, DIVariable V); void addSourceLine(DIE *Die, DIGlobalVariable G); void addSourceLine(DIE *Die, DISubprogram SP); @@ -247,8 +389,8 @@ public: /// addAddress - Add an address attribute to a die based on the location /// provided. - void addAddress(DIE *Die, dwarf::Attribute Attribute, const MachineLocation &Location, - bool Indirect = false); + void addAddress(DIE *Die, dwarf::Attribute Attribute, + const MachineLocation &Location, bool Indirect = false); /// addConstantValue - Add constant value entry in variable DIE. void addConstantValue(DIE *Die, const MachineOperand &MO, DIType Ty); @@ -263,17 +405,17 @@ public: void addTemplateParams(DIE &Buffer, DIArray TParams); /// addRegisterOp - Add register operand. - void addRegisterOp(DIEBlock *TheDie, unsigned Reg); + void addRegisterOp(DIELoc *TheDie, unsigned Reg); /// addRegisterOffset - Add register offset. - void addRegisterOffset(DIEBlock *TheDie, unsigned Reg, int64_t Offset); + void addRegisterOffset(DIELoc *TheDie, unsigned Reg, int64_t Offset); /// addComplexAddress - Start with the address based on the location provided, /// and generate the DWARF information necessary to find the actual variable /// (navigating the extra location information encoded in the type) based on /// the starting location. Add the DWARF information to the die. - /// - void addComplexAddress(const DbgVariable &DV, DIE *Die, dwarf::Attribute Attribute, + void addComplexAddress(const DbgVariable &DV, DIE *Die, + dwarf::Attribute Attribute, const MachineLocation &Location); // FIXME: Should be reformulated in terms of addComplexAddress. @@ -282,8 +424,8 @@ public: /// actual Block variable (navigating the Block struct) based on the /// starting location. Add the DWARF information to the die. Obsolete, /// please use addComplexAddress instead. - /// - void addBlockByrefAddress(const DbgVariable &DV, DIE *Die, dwarf::Attribute Attribute, + void addBlockByrefAddress(const DbgVariable &DV, DIE *Die, + dwarf::Attribute Attribute, const MachineLocation &Location); /// addVariableAddress - Add DW_AT_location attribute for a @@ -294,7 +436,8 @@ public: /// addType - Add a new type attribute to the specified entity. This takes /// and attribute parameter because DW_AT_friend attributes are also /// type references. - void addType(DIE *Entity, DIType Ty, dwarf::Attribute Attribute = dwarf::DW_AT_type); + void addType(DIE *Entity, DIType Ty, + dwarf::Attribute Attribute = dwarf::DW_AT_type); /// getOrCreateNameSpace - Create a DIE for DINameSpace. DIE *getOrCreateNameSpace(DINameSpace NS); @@ -307,10 +450,10 @@ public: DIE *getOrCreateTypeDIE(const MDNode *N); /// getOrCreateContextDIE - Get context owner's DIE. - DIE *getOrCreateContextDIE(DIScope Context); + DIE *createTypeDIE(DICompositeType Ty); - /// createGlobalVariableDIE - create global variable DIE. - void createGlobalVariableDIE(DIGlobalVariable GV); + /// getOrCreateContextDIE - Get context owner's DIE. + DIE *getOrCreateContextDIE(DIScope Context); /// constructContainingTypeDIEs - Construct DIEs for types that contain /// vtables. @@ -319,20 +462,34 @@ public: /// constructVariableDIE - Construct a DIE for the given DbgVariable. DIE *constructVariableDIE(DbgVariable &DV, bool isScopeAbstract); + /// constructSubprogramArguments - Construct function argument DIEs. + void constructSubprogramArguments(DIE &Buffer, DIArray Args); + /// Create a DIE with the given Tag, add the DIE to its parent, and /// call insertDIE if MD is not null. - DIE *createAndAddDIE(unsigned Tag, DIE &Parent, DIDescriptor N = DIDescriptor()); + DIE *createAndAddDIE(unsigned Tag, DIE &Parent, + DIDescriptor N = DIDescriptor()); /// Compute the size of a header for this unit, not including the initial /// length field. - unsigned getHeaderSize() const { + virtual unsigned getHeaderSize() const { return sizeof(int16_t) + // DWARF version number sizeof(int32_t) + // Offset Into Abbrev. Section sizeof(int8_t); // Pointer Size (in bytes) } /// Emit the header for this unit, not including the initial length field. - void emitHeader(const MCSection *ASection, const MCSymbol *ASectionSym); + virtual void emitHeader(const MCSymbol *ASectionSym) const; + + virtual DwarfCompileUnit &getCU() = 0; + +protected: + /// getOrCreateStaticMemberDIE - Create new static data member DIE. + DIE *getOrCreateStaticMemberDIE(DIDerivedType DT); + + /// Look up the source ID with the given directory and source file names. If + /// none currently exists, create a new ID and insert it in the line table. + virtual unsigned getOrCreateSourceID(StringRef File, StringRef Directory) = 0; private: /// constructTypeDIE - Construct basic type die from DIBasicType. @@ -366,12 +523,6 @@ private: void constructTemplateValueParameterDIE(DIE &Buffer, DITemplateValueParameter TVP); - /// getOrCreateStaticMemberDIE - Create new static data member DIE. - DIE *getOrCreateStaticMemberDIE(DIDerivedType DT); - - /// Offset of the CUDie from beginning of debug info section. - unsigned DebugInfoOffset; - /// getLowerBoundDefault - Return the default lower bound for an array. If the /// DWARF version doesn't handle the language, return -1. int64_t getDefaultLowerBound() const; @@ -403,7 +554,71 @@ private: template <typename T> T resolve(DIRef<T> Ref) const { return DD->resolve(Ref); } + + /// If this is a named finished type then include it in the list of types for + /// the accelerator tables. + void updateAcceleratorTables(DIScope Context, DIType Ty, const DIE *TyDIE); }; +class DwarfCompileUnit : public DwarfUnit { + /// The attribute index of DW_AT_stmt_list in the compile unit DIE, avoiding + /// the need to search for it in applyStmtList. + unsigned stmtListIndex; + +public: + DwarfCompileUnit(unsigned UID, DIE *D, DICompileUnit Node, AsmPrinter *A, + DwarfDebug *DW, DwarfFile *DWU); + + void initStmtList(MCSymbol *DwarfLineSectionSym); + + /// Apply the DW_AT_stmt_list from this compile unit to the specified DIE. + void applyStmtList(DIE &D); + + /// createGlobalVariableDIE - create global variable DIE. + void createGlobalVariableDIE(DIGlobalVariable GV); + + /// addLabelAddress - Add a dwarf label attribute data and value using + /// either DW_FORM_addr or DW_FORM_GNU_addr_index. + void addLabelAddress(DIE *Die, dwarf::Attribute Attribute, + const MCSymbol *Label); + + /// addLocalLabelAddress - Add a dwarf label attribute data and value using + /// DW_FORM_addr only. + void addLocalLabelAddress(DIE *Die, dwarf::Attribute Attribute, + const MCSymbol *Label); + + DwarfCompileUnit &getCU() override { return *this; } + + unsigned getOrCreateSourceID(StringRef FileName, StringRef DirName) override; +}; + +class DwarfTypeUnit : public DwarfUnit { +private: + uint64_t TypeSignature; + const DIE *Ty; + DwarfCompileUnit &CU; + MCDwarfDwoLineTable *SplitLineTable; + +public: + DwarfTypeUnit(unsigned UID, DIE *D, DwarfCompileUnit &CU, AsmPrinter *A, + DwarfDebug *DW, DwarfFile *DWU, + MCDwarfDwoLineTable *SplitLineTable = nullptr); + + void setTypeSignature(uint64_t Signature) { TypeSignature = Signature; } + uint64_t getTypeSignature() const { return TypeSignature; } + void setType(const DIE *Ty) { this->Ty = Ty; } + + /// Emit the header for this unit, not including the initial length field. + void emitHeader(const MCSymbol *ASectionSym) const override; + unsigned getHeaderSize() const override { + return DwarfUnit::getHeaderSize() + sizeof(uint64_t) + // Type Signature + sizeof(uint32_t); // Type DIE Offset + } + void initSection(const MCSection *Section); + DwarfCompileUnit &getCU() override { return CU; } + +protected: + unsigned getOrCreateSourceID(StringRef File, StringRef Directory) override; +}; } // end llvm namespace #endif diff --git a/lib/CodeGen/AsmPrinter/ErlangGCPrinter.cpp b/lib/CodeGen/AsmPrinter/ErlangGCPrinter.cpp index a8fb66dcf1..bfcbe6b94e 100644 --- a/lib/CodeGen/AsmPrinter/ErlangGCPrinter.cpp +++ b/lib/CodeGen/AsmPrinter/ErlangGCPrinter.cpp @@ -14,8 +14,8 @@ //===----------------------------------------------------------------------===// #include "llvm/CodeGen/AsmPrinter.h" -#include "llvm/CodeGen/GCs.h" #include "llvm/CodeGen/GCMetadataPrinter.h" +#include "llvm/CodeGen/GCs.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/Function.h" #include "llvm/IR/Instruction.h" @@ -35,8 +35,8 @@ namespace { class ErlangGCPrinter : public GCMetadataPrinter { public: - void beginAssembly(AsmPrinter &AP); - void finishAssembly(AsmPrinter &AP); + void beginAssembly(AsmPrinter &AP) override; + void finishAssembly(AsmPrinter &AP) override; }; } diff --git a/lib/CodeGen/AsmPrinter/LLVMBuild.txt b/lib/CodeGen/AsmPrinter/LLVMBuild.txt index 20b1f7b45b..bbdb0c7fc3 100644 --- a/lib/CodeGen/AsmPrinter/LLVMBuild.txt +++ b/lib/CodeGen/AsmPrinter/LLVMBuild.txt @@ -19,4 +19,4 @@ type = Library name = AsmPrinter parent = Libraries -required_libraries = Analysis CodeGen Core MC MCParser Support Target +required_libraries = Analysis CodeGen Core MC MCParser Support Target TransformUtils diff --git a/lib/CodeGen/AsmPrinter/OcamlGCPrinter.cpp b/lib/CodeGen/AsmPrinter/OcamlGCPrinter.cpp index 98177c0ba1..5a9ecd794a 100644 --- a/lib/CodeGen/AsmPrinter/OcamlGCPrinter.cpp +++ b/lib/CodeGen/AsmPrinter/OcamlGCPrinter.cpp @@ -16,6 +16,7 @@ #include "llvm/CodeGen/AsmPrinter.h" #include "llvm/CodeGen/GCMetadataPrinter.h" #include "llvm/IR/DataLayout.h" +#include "llvm/IR/Mangler.h" #include "llvm/IR/Module.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCContext.h" @@ -23,7 +24,6 @@ #include "llvm/MC/MCSymbol.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/FormattedStream.h" -#include "llvm/Target/Mangler.h" #include "llvm/Target/TargetLoweringObjectFile.h" #include "llvm/Target/TargetMachine.h" #include <cctype> @@ -33,8 +33,8 @@ namespace { class OcamlGCMetadataPrinter : public GCMetadataPrinter { public: - void beginAssembly(AsmPrinter &AP); - void finishAssembly(AsmPrinter &AP); + void beginAssembly(AsmPrinter &AP) override; + void finishAssembly(AsmPrinter &AP) override; }; } diff --git a/lib/CodeGen/AsmPrinter/Win64Exception.cpp b/lib/CodeGen/AsmPrinter/Win64Exception.cpp index 156101286b..17d8bff609 100644 --- a/lib/CodeGen/AsmPrinter/Win64Exception.cpp +++ b/lib/CodeGen/AsmPrinter/Win64Exception.cpp @@ -20,6 +20,7 @@ #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/IR/DataLayout.h" +#include "llvm/IR/Mangler.h" #include "llvm/IR/Module.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCContext.h" @@ -30,7 +31,6 @@ #include "llvm/Support/Dwarf.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/FormattedStream.h" -#include "llvm/Target/Mangler.h" #include "llvm/Target/TargetFrameLowering.h" #include "llvm/Target/TargetLoweringObjectFile.h" #include "llvm/Target/TargetOptions.h" @@ -44,14 +44,14 @@ Win64Exception::Win64Exception(AsmPrinter *A) Win64Exception::~Win64Exception() {} -/// EndModule - Emit all exception information that should come after the +/// endModule - Emit all exception information that should come after the /// content. -void Win64Exception::EndModule() { +void Win64Exception::endModule() { } -/// BeginFunction - Gather pre-function exception information. Assumes it's +/// beginFunction - Gather pre-function exception information. Assumes it's /// being emitted immediately after the function entry point. -void Win64Exception::BeginFunction(const MachineFunction *MF) { +void Win64Exception::beginFunction(const MachineFunction *MF) { shouldEmitMoves = shouldEmitPersonality = shouldEmitLSDA = false; // If any landing pads survive, we need an EH table. @@ -86,9 +86,9 @@ void Win64Exception::BeginFunction(const MachineFunction *MF) { Asm->getFunctionNumber())); } -/// EndFunction - Gather and emit post-function exception information. +/// endFunction - Gather and emit post-function exception information. /// -void Win64Exception::EndFunction() { +void Win64Exception::endFunction(const MachineFunction *) { if (!shouldEmitPersonality && !shouldEmitMoves) return; @@ -101,7 +101,8 @@ void Win64Exception::EndFunction() { if (shouldEmitPersonality) { const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering(); const Function *Per = MMI->getPersonalities()[MMI->getPersonalityIndex()]; - const MCSymbol *Sym = TLOF.getCFIPersonalitySymbol(Per, Asm->Mang, MMI); + const MCSymbol *Sym = + TLOF.getCFIPersonalitySymbol(Per, *Asm->Mang, Asm->TM, MMI); Asm->OutStreamer.PushSection(); Asm->OutStreamer.EmitWin64EHHandlerData(); diff --git a/lib/CodeGen/AsmPrinter/WinCodeViewLineTables.cpp b/lib/CodeGen/AsmPrinter/WinCodeViewLineTables.cpp new file mode 100644 index 0000000000..50b2ca82ec --- /dev/null +++ b/lib/CodeGen/AsmPrinter/WinCodeViewLineTables.cpp @@ -0,0 +1,336 @@ +//===-- llvm/lib/CodeGen/AsmPrinter/WinCodeViewLineTables.cpp --*- C++ -*--===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains support for writing line tables info into COFF files. +// +//===----------------------------------------------------------------------===// + +#include "WinCodeViewLineTables.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/Support/COFF.h" + +namespace llvm { + +StringRef WinCodeViewLineTables::getFullFilepath(const MDNode *S) { + assert(S); + DIDescriptor D(S); + assert((D.isCompileUnit() || D.isFile() || D.isSubprogram() || + D.isLexicalBlockFile() || D.isLexicalBlock()) && + "Unexpected scope info"); + + DIScope Scope(S); + StringRef Dir = Scope.getDirectory(), + Filename = Scope.getFilename(); + char *&Result = DirAndFilenameToFilepathMap[std::make_pair(Dir, Filename)]; + if (Result != 0) + return Result; + + // Clang emits directory and relative filename info into the IR, but CodeView + // operates on full paths. We could change Clang to emit full paths too, but + // that would increase the IR size and probably not needed for other users. + // For now, just concatenate and canonicalize the path here. + std::string Filepath; + if (Filename.find(':') == 1) + Filepath = Filename; + else + Filepath = (Dir + Twine("\\") + Filename).str(); + + // Canonicalize the path. We have to do it textually because we may no longer + // have access the file in the filesystem. + // First, replace all slashes with backslashes. + std::replace(Filepath.begin(), Filepath.end(), '/', '\\'); + + // Remove all "\.\" with "\". + size_t Cursor = 0; + while ((Cursor = Filepath.find("\\.\\", Cursor)) != std::string::npos) + Filepath.erase(Cursor, 2); + + // Replace all "\XXX\..\" with "\". Don't try too hard though as the original + // path should be well-formatted, e.g. start with a drive letter, etc. + Cursor = 0; + while ((Cursor = Filepath.find("\\..\\", Cursor)) != std::string::npos) { + // Something's wrong if the path starts with "\..\", abort. + if (Cursor == 0) + break; + + size_t PrevSlash = Filepath.rfind('\\', Cursor - 1); + if (PrevSlash == std::string::npos) + // Something's wrong, abort. + break; + + Filepath.erase(PrevSlash, Cursor + 3 - PrevSlash); + // The next ".." might be following the one we've just erased. + Cursor = PrevSlash; + } + + // Remove all duplicate backslashes. + Cursor = 0; + while ((Cursor = Filepath.find("\\\\", Cursor)) != std::string::npos) + Filepath.erase(Cursor, 1); + + Result = strdup(Filepath.c_str()); + return StringRef(Result); +} + +void WinCodeViewLineTables::maybeRecordLocation(DebugLoc DL, + const MachineFunction *MF) { + const MDNode *Scope = DL.getScope(MF->getFunction()->getContext()); + if (!Scope) + return; + StringRef Filename = getFullFilepath(Scope); + + // Skip this instruction if it has the same file:line as the previous one. + assert(CurFn); + if (!CurFn->Instrs.empty()) { + const InstrInfoTy &LastInstr = InstrInfo[CurFn->Instrs.back()]; + if (LastInstr.Filename == Filename && LastInstr.LineNumber == DL.getLine()) + return; + } + FileNameRegistry.add(Filename); + + MCSymbol *MCL = Asm->MMI->getContext().CreateTempSymbol(); + Asm->OutStreamer.EmitLabel(MCL); + CurFn->Instrs.push_back(MCL); + InstrInfo[MCL] = InstrInfoTy(Filename, DL.getLine()); +} + +WinCodeViewLineTables::WinCodeViewLineTables(AsmPrinter *AP) + : Asm(0), CurFn(0) { + MachineModuleInfo *MMI = AP->MMI; + + // If module doesn't have named metadata anchors or COFF debug section + // is not available, skip any debug info related stuff. + if (!MMI->getModule()->getNamedMetadata("llvm.dbg.cu") || + !AP->getObjFileLowering().getCOFFDebugSymbolsSection()) + return; + + // Tell MMI that we have debug info. + MMI->setDebugInfoAvailability(true); + Asm = AP; +} + +static void EmitLabelDiff(MCStreamer &Streamer, + const MCSymbol *From, const MCSymbol *To) { + MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None; + MCContext &Context = Streamer.getContext(); + const MCExpr *FromRef = MCSymbolRefExpr::Create(From, Variant, Context), + *ToRef = MCSymbolRefExpr::Create(To, Variant, Context); + const MCExpr *AddrDelta = + MCBinaryExpr::Create(MCBinaryExpr::Sub, ToRef, FromRef, Context); + Streamer.EmitValue(AddrDelta, 4); +} + +void WinCodeViewLineTables::emitDebugInfoForFunction(const Function *GV) { + // For each function there is a separate subsection + // which holds the PC to file:line table. + const MCSymbol *Fn = Asm->getSymbol(GV); + assert(Fn); + + const FunctionInfo &FI = FnDebugInfo[GV]; + if (FI.Instrs.empty()) + return; + assert(FI.End && "Don't know where the function ends?"); + + // PCs/Instructions are grouped into segments sharing the same filename. + // Pre-calculate the lengths (in instructions) of these segments and store + // them in a map for convenience. Each index in the map is the sequential + // number of the respective instruction that starts a new segment. + DenseMap<size_t, size_t> FilenameSegmentLengths; + size_t LastSegmentEnd = 0; + StringRef PrevFilename = InstrInfo[FI.Instrs[0]].Filename; + for (size_t J = 1, F = FI.Instrs.size(); J != F; ++J) { + if (PrevFilename == InstrInfo[FI.Instrs[J]].Filename) + continue; + FilenameSegmentLengths[LastSegmentEnd] = J - LastSegmentEnd; + LastSegmentEnd = J; + PrevFilename = InstrInfo[FI.Instrs[J]].Filename; + } + FilenameSegmentLengths[LastSegmentEnd] = FI.Instrs.size() - LastSegmentEnd; + + // Emit the control code of the subsection followed by the payload size. + Asm->OutStreamer.AddComment( + "Linetable subsection for " + Twine(Fn->getName())); + Asm->EmitInt32(COFF::DEBUG_LINE_TABLE_SUBSECTION); + MCSymbol *SubsectionBegin = Asm->MMI->getContext().CreateTempSymbol(), + *SubsectionEnd = Asm->MMI->getContext().CreateTempSymbol(); + EmitLabelDiff(Asm->OutStreamer, SubsectionBegin, SubsectionEnd); + Asm->OutStreamer.EmitLabel(SubsectionBegin); + + // Identify the function this subsection is for. + Asm->OutStreamer.EmitCOFFSecRel32(Fn); + Asm->OutStreamer.EmitCOFFSectionIndex(Fn); + + // Length of the function's code, in bytes. + EmitLabelDiff(Asm->OutStreamer, Fn, FI.End); + + // PC-to-linenumber lookup table: + MCSymbol *FileSegmentEnd = 0; + for (size_t J = 0, F = FI.Instrs.size(); J != F; ++J) { + MCSymbol *Instr = FI.Instrs[J]; + assert(InstrInfo.count(Instr)); + + if (FilenameSegmentLengths.count(J)) { + // We came to a beginning of a new filename segment. + if (FileSegmentEnd) + Asm->OutStreamer.EmitLabel(FileSegmentEnd); + StringRef CurFilename = InstrInfo[FI.Instrs[J]].Filename; + assert(FileNameRegistry.Infos.count(CurFilename)); + size_t IndexInStringTable = + FileNameRegistry.Infos[CurFilename].FilenameID; + // Each segment starts with the offset of the filename + // in the string table. + Asm->OutStreamer.AddComment( + "Segment for file '" + Twine(CurFilename) + "' begins"); + MCSymbol *FileSegmentBegin = Asm->MMI->getContext().CreateTempSymbol(); + Asm->OutStreamer.EmitLabel(FileSegmentBegin); + Asm->EmitInt32(8 * IndexInStringTable); + + // Number of PC records in the lookup table. + size_t SegmentLength = FilenameSegmentLengths[J]; + Asm->EmitInt32(SegmentLength); + + // Full size of the segment for this filename, including the prev two + // records. + FileSegmentEnd = Asm->MMI->getContext().CreateTempSymbol(); + EmitLabelDiff(Asm->OutStreamer, FileSegmentBegin, FileSegmentEnd); + } + + // The first PC with the given linenumber and the linenumber itself. + EmitLabelDiff(Asm->OutStreamer, Fn, Instr); + Asm->EmitInt32(InstrInfo[Instr].LineNumber); + } + + if (FileSegmentEnd) + Asm->OutStreamer.EmitLabel(FileSegmentEnd); + Asm->OutStreamer.EmitLabel(SubsectionEnd); +} + +void WinCodeViewLineTables::endModule() { + if (FnDebugInfo.empty()) + return; + + assert(Asm != 0); + Asm->OutStreamer.SwitchSection( + Asm->getObjFileLowering().getCOFFDebugSymbolsSection()); + Asm->EmitInt32(COFF::DEBUG_SECTION_MAGIC); + + // The COFF .debug$S section consists of several subsections, each starting + // with a 4-byte control code (e.g. 0xF1, 0xF2, etc) and then a 4-byte length + // of the payload followed by the payload itself. The subsections are 4-byte + // aligned. + + for (size_t I = 0, E = VisitedFunctions.size(); I != E; ++I) + emitDebugInfoForFunction(VisitedFunctions[I]); + + // This subsection holds a file index to offset in string table table. + Asm->OutStreamer.AddComment("File index to string table offset subsection"); + Asm->EmitInt32(COFF::DEBUG_INDEX_SUBSECTION); + size_t NumFilenames = FileNameRegistry.Infos.size(); + Asm->EmitInt32(8 * NumFilenames); + for (size_t I = 0, E = FileNameRegistry.Filenames.size(); I != E; ++I) { + StringRef Filename = FileNameRegistry.Filenames[I]; + // For each unique filename, just write it's offset in the string table. + Asm->EmitInt32(FileNameRegistry.Infos[Filename].StartOffset); + // The function name offset is not followed by any additional data. + Asm->EmitInt32(0); + } + + // This subsection holds the string table. + Asm->OutStreamer.AddComment("String table"); + Asm->EmitInt32(COFF::DEBUG_STRING_TABLE_SUBSECTION); + Asm->EmitInt32(FileNameRegistry.LastOffset); + // The payload starts with a null character. + Asm->EmitInt8(0); + + for (size_t I = 0, E = FileNameRegistry.Filenames.size(); I != E; ++I) { + // Just emit unique filenames one by one, separated by a null character. + Asm->OutStreamer.EmitBytes(FileNameRegistry.Filenames[I]); + Asm->EmitInt8(0); + } + + // No more subsections. Fill with zeros to align the end of the section by 4. + Asm->OutStreamer.EmitFill((-FileNameRegistry.LastOffset) % 4, 0); + + clear(); +} + +void WinCodeViewLineTables::beginFunction(const MachineFunction *MF) { + assert(!CurFn && "Can't process two functions at once!"); + + if (!Asm || !Asm->MMI->hasDebugInfo()) + return; + + const Function *GV = MF->getFunction(); + assert(FnDebugInfo.count(GV) == false); + VisitedFunctions.push_back(GV); + CurFn = &FnDebugInfo[GV]; + + // Find the end of the function prolog. + // FIXME: is there a simpler a way to do this? Can we just search + // for the first instruction of the function, not the last of the prolog? + DebugLoc PrologEndLoc; + bool EmptyPrologue = true; + for (MachineFunction::const_iterator I = MF->begin(), E = MF->end(); + I != E && PrologEndLoc.isUnknown(); ++I) { + for (MachineBasicBlock::const_iterator II = I->begin(), IE = I->end(); + II != IE; ++II) { + const MachineInstr *MI = II; + if (MI->isDebugValue()) + continue; + + // First known non-DBG_VALUE and non-frame setup location marks + // the beginning of the function body. + // FIXME: do we need the first subcondition? + if (!MI->getFlag(MachineInstr::FrameSetup) && + (!MI->getDebugLoc().isUnknown())) { + PrologEndLoc = MI->getDebugLoc(); + break; + } + EmptyPrologue = false; + } + } + // Record beginning of function if we have a non-empty prologue. + if (!PrologEndLoc.isUnknown() && !EmptyPrologue) { + DebugLoc FnStartDL = + PrologEndLoc.getFnDebugLoc(MF->getFunction()->getContext()); + maybeRecordLocation(FnStartDL, MF); + } +} + +void WinCodeViewLineTables::endFunction(const MachineFunction *MF) { + if (!Asm || !CurFn) // We haven't created any debug info for this function. + return; + + const Function *GV = MF->getFunction(); + assert(FnDebugInfo.count(GV) == true); + assert(CurFn == &FnDebugInfo[GV]); + + if (CurFn->Instrs.empty()) { + FnDebugInfo.erase(GV); + VisitedFunctions.pop_back(); + } else { + // Define end label for subprogram. + MCSymbol *FunctionEndSym = Asm->OutStreamer.getContext().CreateTempSymbol(); + Asm->OutStreamer.EmitLabel(FunctionEndSym); + CurFn->End = FunctionEndSym; + } + CurFn = 0; +} + +void WinCodeViewLineTables::beginInstruction(const MachineInstr *MI) { + // Ignore DBG_VALUE locations and function prologue. + if (!Asm || MI->isDebugValue() || MI->getFlag(MachineInstr::FrameSetup)) + return; + DebugLoc DL = MI->getDebugLoc(); + if (DL == PrevInstLoc || DL.isUnknown()) + return; + maybeRecordLocation(DL, Asm->MF); +} +} diff --git a/lib/CodeGen/AsmPrinter/WinCodeViewLineTables.h b/lib/CodeGen/AsmPrinter/WinCodeViewLineTables.h new file mode 100644 index 0000000000..a7a62053c3 --- /dev/null +++ b/lib/CodeGen/AsmPrinter/WinCodeViewLineTables.h @@ -0,0 +1,144 @@ +//===-- llvm/lib/CodeGen/AsmPrinter/WinCodeViewLineTables.h ----*- C++ -*--===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains support for writing line tables info into COFF files. +// +//===----------------------------------------------------------------------===// + +#ifndef CODEGEN_ASMPRINTER_WINCODEVIEWLINETABLES_H__ +#define CODEGEN_ASMPRINTER_WINCODEVIEWLINETABLES_H__ + +#include "AsmPrinterHandler.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/CodeGen/AsmPrinter.h" +#include "llvm/CodeGen/LexicalScopes.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/IR/DebugInfo.h" +#include "llvm/IR/DebugLoc.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/Target/TargetLoweringObjectFile.h" + +namespace llvm { +/// \brief Collects and handles line tables information in a CodeView format. +class WinCodeViewLineTables : public AsmPrinterHandler { + AsmPrinter *Asm; + DebugLoc PrevInstLoc; + + // For each function, store a vector of labels to its instructions, as well as + // to the end of the function. + struct FunctionInfo { + SmallVector<MCSymbol *, 10> Instrs; + MCSymbol *End; + FunctionInfo() : End(0) {} + } *CurFn; + + typedef DenseMap<const Function *, FunctionInfo> FnDebugInfoTy; + FnDebugInfoTy FnDebugInfo; + // Store the functions we've visited in a vector so we can maintain a stable + // order while emitting subsections. + SmallVector<const Function *, 10> VisitedFunctions; + + // InstrInfoTy - Holds the Filename:LineNumber information for every + // instruction with a unique debug location. + struct InstrInfoTy { + StringRef Filename; + unsigned LineNumber; + + InstrInfoTy() : LineNumber(0) {} + + InstrInfoTy(StringRef Filename, unsigned LineNumber) + : Filename(Filename), LineNumber(LineNumber) {} + }; + DenseMap<MCSymbol *, InstrInfoTy> InstrInfo; + + // FileNameRegistry - Manages filenames observed while generating debug info + // by filtering out duplicates and bookkeeping the offsets in the string + // table to be generated. + struct FileNameRegistryTy { + SmallVector<StringRef, 10> Filenames; + struct PerFileInfo { + size_t FilenameID, StartOffset; + }; + StringMap<PerFileInfo> Infos; + + // The offset in the string table where we'll write the next unique + // filename. + size_t LastOffset; + + FileNameRegistryTy() { + clear(); + } + + // Add Filename to the registry, if it was not observed before. + void add(StringRef Filename) { + if (Infos.count(Filename)) + return; + size_t OldSize = Infos.size(); + Infos[Filename].FilenameID = OldSize; + Infos[Filename].StartOffset = LastOffset; + LastOffset += Filename.size() + 1; + Filenames.push_back(Filename); + } + + void clear() { + LastOffset = 1; + Infos.clear(); + Filenames.clear(); + } + } FileNameRegistry; + + typedef std::map<std::pair<StringRef, StringRef>, char *> + DirAndFilenameToFilepathMapTy; + DirAndFilenameToFilepathMapTy DirAndFilenameToFilepathMap; + StringRef getFullFilepath(const MDNode *S); + + void maybeRecordLocation(DebugLoc DL, const MachineFunction *MF); + + void clear() { + assert(CurFn == 0); + FileNameRegistry.clear(); + InstrInfo.clear(); + } + + void emitDebugInfoForFunction(const Function *GV); + +public: + WinCodeViewLineTables(AsmPrinter *Asm); + + ~WinCodeViewLineTables() { + for (DirAndFilenameToFilepathMapTy::iterator + I = DirAndFilenameToFilepathMap.begin(), + E = DirAndFilenameToFilepathMap.end(); + I != E; ++I) + free(I->second); + } + + void setSymbolSize(const llvm::MCSymbol *, uint64_t) override {} + + /// \brief Emit the COFF section that holds the line table information. + void endModule() override; + + /// \brief Gather pre-function debug information. + void beginFunction(const MachineFunction *MF) override; + + /// \brief Gather post-function debug information. + void endFunction(const MachineFunction *) override; + + /// \brief Process beginning of an instruction. + void beginInstruction(const MachineInstr *MI) override; + + /// \brief Process end of an instruction. + void endInstruction() override {} +}; +} // End of namespace llvm + +#endif |