From: David Blaikie Date: Sat, 4 Oct 2014 15:49:50 +0000 (+0000) Subject: Move DwarfCompileUnit from DwarfUnit.h to its own header (DwarfCompileUnit.h) X-Git-Url: http://plrg.eecs.uci.edu/git/?p=oota-llvm.git;a=commitdiff_plain;h=a2ec9db66b068d327deb94ad8661209d1476c5ba Move DwarfCompileUnit from DwarfUnit.h to its own header (DwarfCompileUnit.h) In preparation for sinking all the subprogram emission code down from DwarfDebug into DwarfCompileUnit, this will avoid bloating DwarfUnit.h/cpp greatly and make concerns a bit more clear/isolated. (sinking this handling down is part of the work to handle emitting minimal subprograms for -gmlt-like data into the skeleton CU under fission) git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@219057 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/AsmPrinter/CMakeLists.txt b/lib/CodeGen/AsmPrinter/CMakeLists.txt index f555f212a97..e6b7d648abf 100644 --- a/lib/CodeGen/AsmPrinter/CMakeLists.txt +++ b/lib/CodeGen/AsmPrinter/CMakeLists.txt @@ -9,6 +9,7 @@ add_llvm_library(LLVMAsmPrinter DIEHash.cpp DwarfAccelTable.cpp DwarfCFIException.cpp + DwarfCompileUnit.cpp DwarfDebug.cpp DwarfFile.cpp DwarfStringPool.cpp diff --git a/lib/CodeGen/AsmPrinter/DIE.cpp b/lib/CodeGen/AsmPrinter/DIE.cpp index c3dcd9c8c19..25dec5893c6 100644 --- a/lib/CodeGen/AsmPrinter/DIE.cpp +++ b/lib/CodeGen/AsmPrinter/DIE.cpp @@ -12,6 +12,8 @@ //===----------------------------------------------------------------------===// #include "DIE.h" + +#include "DwarfCompileUnit.h" #include "DwarfDebug.h" #include "DwarfUnit.h" #include "llvm/ADT/Twine.h" diff --git a/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp b/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp new file mode 100644 index 00000000000..b7a56e32513 --- /dev/null +++ b/lib/CodeGen/AsmPrinter/DwarfCompileUnit.cpp @@ -0,0 +1,277 @@ +#include "DwarfCompileUnit.h" + +#include "llvm/IR/DataLayout.h" +#include "llvm/IR/GlobalValue.h" +#include "llvm/IR/GlobalVariable.h" +#include "llvm/IR/Instruction.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/Target/TargetLoweringObjectFile.h" + +namespace llvm { + +DwarfCompileUnit::DwarfCompileUnit(unsigned UID, DICompileUnit Node, + AsmPrinter *A, DwarfDebug *DW, + DwarfFile *DWU) + : DwarfUnit(UID, dwarf::DW_TAG_compile_unit, Node, A, DW, DWU) { + insertDIE(Node, &getUnitDie()); +} + +/// addLabelAddress - Add a dwarf label attribute data and value using +/// DW_FORM_addr or DW_FORM_GNU_addr_index. +/// +void DwarfCompileUnit::addLabelAddress(DIE &Die, dwarf::Attribute Attribute, + const MCSymbol *Label) { + + // Don't use the address pool in non-fission or in the skeleton unit itself. + // FIXME: Once GDB supports this, it's probably worthwhile using the address + // pool from the skeleton - maybe even in non-fission (possibly fewer + // relocations by sharing them in the pool, but we have other ideas about how + // to reduce the number of relocations as well/instead). + if (!DD->useSplitDwarf() || !Skeleton) + return addLocalLabelAddress(Die, Attribute, Label); + + if (Label) + DD->addArangeLabel(SymbolCU(this, Label)); + + unsigned idx = DD->getAddressPool().getIndex(Label); + DIEValue *Value = new (DIEValueAllocator) DIEInteger(idx); + Die.addValue(Attribute, dwarf::DW_FORM_GNU_addr_index, Value); +} + +void DwarfCompileUnit::addLocalLabelAddress(DIE &Die, + dwarf::Attribute Attribute, + const MCSymbol *Label) { + if (Label) + DD->addArangeLabel(SymbolCU(this, Label)); + + Die.addValue(Attribute, dwarf::DW_FORM_addr, + Label ? (DIEValue *)new (DIEValueAllocator) DIELabel(Label) + : new (DIEValueAllocator) DIEInteger(0)); +} + +unsigned DwarfCompileUnit::getOrCreateSourceID(StringRef FileName, StringRef DirName) { + // If we print assembly, we can't separate .file entries according to + // compile units. Thus all files will belong to the default compile unit. + + // FIXME: add a better feature test than hasRawTextSupport. Even better, + // extend .file to support this. + return Asm->OutStreamer.EmitDwarfFileDirective( + 0, DirName, FileName, + Asm->OutStreamer.hasRawTextSupport() ? 0 : getUniqueID()); +} + +// Return const expression if value is a GEP to access merged global +// constant. e.g. +// i8* getelementptr ({ i8, i8, i8, i8 }* @_MergedGlobals, i32 0, i32 0) +static const ConstantExpr *getMergedGlobalExpr(const Value *V) { + const ConstantExpr *CE = dyn_cast_or_null(V); + if (!CE || CE->getNumOperands() != 3 || + CE->getOpcode() != Instruction::GetElementPtr) + return nullptr; + + // First operand points to a global struct. + Value *Ptr = CE->getOperand(0); + if (!isa(Ptr) || + !isa(cast(Ptr->getType())->getElementType())) + return nullptr; + + // Second operand is zero. + const ConstantInt *CI = dyn_cast_or_null(CE->getOperand(1)); + if (!CI || !CI->isZero()) + return nullptr; + + // Third operand is offset. + if (!isa(CE->getOperand(2))) + return nullptr; + + return CE; +} + +/// getOrCreateGlobalVariableDIE - get or create global variable DIE. +DIE *DwarfCompileUnit::getOrCreateGlobalVariableDIE(DIGlobalVariable GV) { + // Check for pre-existence. + if (DIE *Die = getDIE(GV)) + return Die; + + assert(GV.isGlobalVariable()); + + DIScope GVContext = GV.getContext(); + DIType GTy = DD->resolve(GV.getType()); + + // If this is a static data member definition, some attributes belong + // to the declaration DIE. + DIE *VariableDIE = nullptr; + bool IsStaticMember = false; + DIDerivedType SDMDecl = GV.getStaticDataMemberDeclaration(); + if (SDMDecl.Verify()) { + assert(SDMDecl.isStaticMember() && "Expected static member decl"); + // We need the declaration DIE that is in the static member's class. + VariableDIE = getOrCreateStaticMemberDIE(SDMDecl); + IsStaticMember = true; + } + + // If this is not a static data member definition, create the variable + // DIE and add the initial set of attributes to it. + if (!VariableDIE) { + // Construct the context before querying for the existence of the DIE in + // case such construction creates the DIE. + DIE *ContextDIE = getOrCreateContextDIE(GVContext); + + // Add to map. + VariableDIE = &createAndAddDIE(GV.getTag(), *ContextDIE, GV); + + // Add name and type. + addString(*VariableDIE, dwarf::DW_AT_name, GV.getDisplayName()); + addType(*VariableDIE, GTy); + + // Add scoping info. + if (!GV.isLocalToUnit()) + addFlag(*VariableDIE, dwarf::DW_AT_external); + + // Add line number info. + addSourceLine(*VariableDIE, GV); + } + + // Add location. + bool addToAccelTable = false; + DIE *VariableSpecDIE = nullptr; + bool isGlobalVariable = GV.getGlobal() != nullptr; + if (isGlobalVariable) { + addToAccelTable = true; + DIELoc *Loc = new (DIEValueAllocator) DIELoc(); + const MCSymbol *Sym = Asm->getSymbol(GV.getGlobal()); + if (GV.getGlobal()->isThreadLocal()) { + // FIXME: Make this work with -gsplit-dwarf. + unsigned PointerSize = Asm->getDataLayout().getPointerSize(); + assert((PointerSize == 4 || PointerSize == 8) && + "Add support for other sizes if necessary"); + // Based on GCC's support for TLS: + if (!DD->useSplitDwarf()) { + // 1) Start with a constNu of the appropriate pointer size + addUInt(*Loc, dwarf::DW_FORM_data1, + PointerSize == 4 ? dwarf::DW_OP_const4u : dwarf::DW_OP_const8u); + // 2) containing the (relocated) offset of the TLS variable + // within the module's TLS block. + addExpr(*Loc, dwarf::DW_FORM_udata, + Asm->getObjFileLowering().getDebugThreadLocalSymbol(Sym)); + } else { + addUInt(*Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_GNU_const_index); + addUInt(*Loc, dwarf::DW_FORM_udata, + DD->getAddressPool().getIndex(Sym, /* TLS */ true)); + } + // 3) followed by a custom OP to make the debugger do a TLS lookup. + addUInt(*Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_GNU_push_tls_address); + } else { + DD->addArangeLabel(SymbolCU(this, Sym)); + addOpAddress(*Loc, Sym); + } + // A static member's declaration is already flagged as such. + if (!SDMDecl.Verify() && !GV.isDefinition()) + addFlag(*VariableDIE, dwarf::DW_AT_declaration); + // Do not create specification DIE if context is either compile unit + // or a subprogram. + if (GVContext && GV.isDefinition() && !GVContext.isCompileUnit() && + !GVContext.isFile() && !DD->isSubprogramContext(GVContext)) { + // Create specification DIE. + VariableSpecDIE = &createAndAddDIE(dwarf::DW_TAG_variable, UnitDie); + addDIEEntry(*VariableSpecDIE, dwarf::DW_AT_specification, *VariableDIE); + addBlock(*VariableSpecDIE, dwarf::DW_AT_location, Loc); + // A static member's declaration is already flagged as such. + if (!SDMDecl.Verify()) + addFlag(*VariableDIE, dwarf::DW_AT_declaration); + } else { + addBlock(*VariableDIE, dwarf::DW_AT_location, Loc); + } + // Add the linkage name. + StringRef LinkageName = GV.getLinkageName(); + if (!LinkageName.empty()) + // From DWARF4: DIEs to which DW_AT_linkage_name may apply include: + // TAG_common_block, TAG_constant, TAG_entry_point, TAG_subprogram and + // TAG_variable. + addString(IsStaticMember && VariableSpecDIE ? *VariableSpecDIE + : *VariableDIE, + DD->getDwarfVersion() >= 4 ? dwarf::DW_AT_linkage_name + : dwarf::DW_AT_MIPS_linkage_name, + GlobalValue::getRealLinkageName(LinkageName)); + } else if (const ConstantInt *CI = + dyn_cast_or_null(GV.getConstant())) { + // AT_const_value was added when the static member was created. To avoid + // emitting AT_const_value multiple times, we only add AT_const_value when + // it is not a static member. + if (!IsStaticMember) + addConstantValue(*VariableDIE, CI, GTy); + } else if (const ConstantExpr *CE = getMergedGlobalExpr(GV.getConstant())) { + addToAccelTable = true; + // GV is a merged global. + DIELoc *Loc = new (DIEValueAllocator) DIELoc(); + Value *Ptr = CE->getOperand(0); + MCSymbol *Sym = Asm->getSymbol(cast(Ptr)); + DD->addArangeLabel(SymbolCU(this, Sym)); + addOpAddress(*Loc, Sym); + addUInt(*Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_constu); + SmallVector Idx(CE->op_begin() + 1, CE->op_end()); + addUInt(*Loc, dwarf::DW_FORM_udata, + Asm->getDataLayout().getIndexedOffset(Ptr->getType(), Idx)); + addUInt(*Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_plus); + addBlock(*VariableDIE, dwarf::DW_AT_location, Loc); + } + + DIE *ResultDIE = VariableSpecDIE ? VariableSpecDIE : VariableDIE; + + if (addToAccelTable) { + DD->addAccelName(GV.getName(), *ResultDIE); + + // If the linkage name is different than the name, go ahead and output + // that as well into the name table. + if (GV.getLinkageName() != "" && GV.getName() != GV.getLinkageName()) + DD->addAccelName(GV.getLinkageName(), *ResultDIE); + } + + addGlobalName(GV.getName(), *ResultDIE, GV.getContext()); + return ResultDIE; +} + +void DwarfCompileUnit::addRange(RangeSpan Range) { + bool SameAsPrevCU = this == DD->getPrevCU(); + DD->setPrevCU(this); + // If we have no current ranges just add the range and return, otherwise, + // check the current section and CU against the previous section and CU we + // emitted into and the subprogram was contained within. If these are the + // same then extend our current range, otherwise add this as a new range. + if (CURanges.empty() || !SameAsPrevCU || + (&CURanges.back().getEnd()->getSection() != + &Range.getEnd()->getSection())) { + CURanges.push_back(Range); + return; + } + + CURanges.back().setEnd(Range.getEnd()); +} + +void DwarfCompileUnit::initStmtList(MCSymbol *DwarfLineSectionSym) { + // Define start line table label for each Compile Unit. + MCSymbol *LineTableStartSym = + Asm->OutStreamer.getDwarfLineTableSymbol(getUniqueID()); + + stmtListIndex = UnitDie.getValues().size(); + + // DW_AT_stmt_list is a offset of line number information for this + // compile unit in debug_line section. For split dwarf this is + // left in the skeleton CU and so not included. + // The line table entries are not always emitted in assembly, so it + // is not okay to use line_table_start here. + if (Asm->MAI->doesDwarfUseRelocationsAcrossSections()) + addSectionLabel(UnitDie, dwarf::DW_AT_stmt_list, LineTableStartSym); + else + addSectionDelta(UnitDie, dwarf::DW_AT_stmt_list, LineTableStartSym, + DwarfLineSectionSym); +} + +void DwarfCompileUnit::applyStmtList(DIE &D) { + D.addValue(dwarf::DW_AT_stmt_list, + UnitDie.getAbbrev().getData()[stmtListIndex].getForm(), + UnitDie.getValues()[stmtListIndex]); +} + +} // end llvm namespace diff --git a/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h b/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h new file mode 100644 index 00000000000..bced5335e28 --- /dev/null +++ b/lib/CodeGen/AsmPrinter/DwarfCompileUnit.h @@ -0,0 +1,67 @@ +//===-- llvm/CodeGen/DwarfCompileUnit.h - Dwarf Compile Unit ---*- C++ -*--===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains support for writing dwarf compile unit. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_CODEGEN_ASMPRINTER_DWARFCOMPILEUNIT_H +#define LLVM_LIB_CODEGEN_ASMPRINTER_DWARFCOMPILEUNIT_H + +#include "DwarfUnit.h" +#include "llvm/Support/Dwarf.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/IR/DebugInfo.h" + +namespace llvm { + +class AsmPrinter; +class DIE; +class DwarfDebug; +class DwarfFile; +class MCSymbol; + +class DwarfCompileUnit : public DwarfUnit { + /// The attribute index of DW_AT_stmt_list in the compile unit DIE, avoiding + /// the need to search for it in applyStmtList. + unsigned stmtListIndex; + +public: + DwarfCompileUnit(unsigned UID, DICompileUnit Node, AsmPrinter *A, + DwarfDebug *DW, DwarfFile *DWU); + + void initStmtList(MCSymbol *DwarfLineSectionSym); + + /// Apply the DW_AT_stmt_list from this compile unit to the specified DIE. + void applyStmtList(DIE &D); + + /// getOrCreateGlobalVariableDIE - get or create global variable DIE. + DIE *getOrCreateGlobalVariableDIE(DIGlobalVariable GV); + + /// addLabelAddress - Add a dwarf label attribute data and value using + /// either DW_FORM_addr or DW_FORM_GNU_addr_index. + void addLabelAddress(DIE &Die, dwarf::Attribute Attribute, + const MCSymbol *Label); + + /// addLocalLabelAddress - Add a dwarf label attribute data and value using + /// DW_FORM_addr only. + void addLocalLabelAddress(DIE &Die, dwarf::Attribute Attribute, + const MCSymbol *Label); + + DwarfCompileUnit &getCU() override { return *this; } + + unsigned getOrCreateSourceID(StringRef FileName, StringRef DirName) override; + + /// addRange - Add an address range to the list of ranges for this unit. + void addRange(RangeSpan Range); +}; + +} // end llvm namespace + +#endif diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp index c54fc989569..a19750a4904 100644 --- a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -11,8 +11,10 @@ // //===----------------------------------------------------------------------===// -#include "ByteStreamer.h" #include "DwarfDebug.h" + +#include "ByteStreamer.h" +#include "DwarfCompileUnit.h" #include "DIE.h" #include "DIEHash.h" #include "DwarfUnit.h" diff --git a/lib/CodeGen/AsmPrinter/DwarfUnit.cpp b/lib/CodeGen/AsmPrinter/DwarfUnit.cpp index 902dafa6f46..59b47eece59 100644 --- a/lib/CodeGen/AsmPrinter/DwarfUnit.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfUnit.cpp @@ -12,7 +12,9 @@ //===----------------------------------------------------------------------===// #include "DwarfUnit.h" + #include "DwarfAccelTable.h" +#include "DwarfCompileUnit.h" #include "DwarfDebug.h" #include "llvm/ADT/APFloat.h" #include "llvm/IR/Constants.h" @@ -52,13 +54,6 @@ DwarfUnit::DwarfUnit(unsigned UID, dwarf::Tag UnitTag, DICompileUnit Node, DIEIntegerOne = new (DIEValueAllocator) DIEInteger(1); } -DwarfCompileUnit::DwarfCompileUnit(unsigned UID, DICompileUnit Node, - AsmPrinter *A, DwarfDebug *DW, - DwarfFile *DWU) - : DwarfUnit(UID, dwarf::DW_TAG_compile_unit, Node, A, DW, DWU) { - insertDIE(Node, &getUnitDie()); -} - DwarfTypeUnit::DwarfTypeUnit(unsigned UID, DwarfCompileUnit &CU, AsmPrinter *A, DwarfDebug *DW, DwarfFile *DWU, MCDwarfDwoLineTable *SplitLineTable) @@ -280,50 +275,6 @@ void DwarfUnit::addSectionOffset(DIE &Die, dwarf::Attribute Attribute, addUInt(Die, Attribute, dwarf::DW_FORM_data4, Integer); } -/// addLabelAddress - Add a dwarf label attribute data and value using -/// DW_FORM_addr or DW_FORM_GNU_addr_index. -/// -void DwarfCompileUnit::addLabelAddress(DIE &Die, dwarf::Attribute Attribute, - const MCSymbol *Label) { - - // Don't use the address pool in non-fission or in the skeleton unit itself. - // FIXME: Once GDB supports this, it's probably worthwhile using the address - // pool from the skeleton - maybe even in non-fission (possibly fewer - // relocations by sharing them in the pool, but we have other ideas about how - // to reduce the number of relocations as well/instead). - if (!DD->useSplitDwarf() || !Skeleton) - return addLocalLabelAddress(Die, Attribute, Label); - - if (Label) - DD->addArangeLabel(SymbolCU(this, Label)); - - unsigned idx = DD->getAddressPool().getIndex(Label); - DIEValue *Value = new (DIEValueAllocator) DIEInteger(idx); - Die.addValue(Attribute, dwarf::DW_FORM_GNU_addr_index, Value); -} - -void DwarfCompileUnit::addLocalLabelAddress(DIE &Die, - dwarf::Attribute Attribute, - const MCSymbol *Label) { - if (Label) - DD->addArangeLabel(SymbolCU(this, Label)); - - Die.addValue(Attribute, dwarf::DW_FORM_addr, - Label ? (DIEValue *)new (DIEValueAllocator) DIELabel(Label) - : new (DIEValueAllocator) DIEInteger(0)); -} - -unsigned DwarfCompileUnit::getOrCreateSourceID(StringRef FileName, StringRef DirName) { - // If we print assembly, we can't separate .file entries according to - // compile units. Thus all files will belong to the default compile unit. - - // FIXME: add a better feature test than hasRawTextSupport. Even better, - // extend .file to support this. - return Asm->OutStreamer.EmitDwarfFileDirective( - 0, DirName, FileName, - Asm->OutStreamer.hasRawTextSupport() ? 0 : getUniqueID()); -} - unsigned DwarfTypeUnit::getOrCreateSourceID(StringRef FileName, StringRef DirName) { return SplitLineTable ? SplitLineTable->getFile(DirName, FileName) : getCU().getOrCreateSourceID(FileName, DirName); @@ -1573,177 +1524,6 @@ void DwarfUnit::applyVariableAttributes(const DbgVariable &Var, addFlag(VariableDie, dwarf::DW_AT_artificial); } -// Return const expression if value is a GEP to access merged global -// constant. e.g. -// i8* getelementptr ({ i8, i8, i8, i8 }* @_MergedGlobals, i32 0, i32 0) -static const ConstantExpr *getMergedGlobalExpr(const Value *V) { - const ConstantExpr *CE = dyn_cast_or_null(V); - if (!CE || CE->getNumOperands() != 3 || - CE->getOpcode() != Instruction::GetElementPtr) - return nullptr; - - // First operand points to a global struct. - Value *Ptr = CE->getOperand(0); - if (!isa(Ptr) || - !isa(cast(Ptr->getType())->getElementType())) - return nullptr; - - // Second operand is zero. - const ConstantInt *CI = dyn_cast_or_null(CE->getOperand(1)); - if (!CI || !CI->isZero()) - return nullptr; - - // Third operand is offset. - if (!isa(CE->getOperand(2))) - return nullptr; - - return CE; -} - -/// getOrCreateGlobalVariableDIE - get or create global variable DIE. -DIE *DwarfCompileUnit::getOrCreateGlobalVariableDIE(DIGlobalVariable GV) { - // Check for pre-existence. - if (DIE *Die = getDIE(GV)) - return Die; - - assert(GV.isGlobalVariable()); - - DIScope GVContext = GV.getContext(); - DIType GTy = DD->resolve(GV.getType()); - - // If this is a static data member definition, some attributes belong - // to the declaration DIE. - DIE *VariableDIE = nullptr; - bool IsStaticMember = false; - DIDerivedType SDMDecl = GV.getStaticDataMemberDeclaration(); - if (SDMDecl.Verify()) { - assert(SDMDecl.isStaticMember() && "Expected static member decl"); - // We need the declaration DIE that is in the static member's class. - VariableDIE = getOrCreateStaticMemberDIE(SDMDecl); - IsStaticMember = true; - } - - // If this is not a static data member definition, create the variable - // DIE and add the initial set of attributes to it. - if (!VariableDIE) { - // Construct the context before querying for the existence of the DIE in - // case such construction creates the DIE. - DIE *ContextDIE = getOrCreateContextDIE(GVContext); - - // Add to map. - VariableDIE = &createAndAddDIE(GV.getTag(), *ContextDIE, GV); - - // Add name and type. - addString(*VariableDIE, dwarf::DW_AT_name, GV.getDisplayName()); - addType(*VariableDIE, GTy); - - // Add scoping info. - if (!GV.isLocalToUnit()) - addFlag(*VariableDIE, dwarf::DW_AT_external); - - // Add line number info. - addSourceLine(*VariableDIE, GV); - } - - // Add location. - bool addToAccelTable = false; - DIE *VariableSpecDIE = nullptr; - bool isGlobalVariable = GV.getGlobal() != nullptr; - if (isGlobalVariable) { - addToAccelTable = true; - DIELoc *Loc = new (DIEValueAllocator) DIELoc(); - const MCSymbol *Sym = Asm->getSymbol(GV.getGlobal()); - if (GV.getGlobal()->isThreadLocal()) { - // FIXME: Make this work with -gsplit-dwarf. - unsigned PointerSize = Asm->getDataLayout().getPointerSize(); - assert((PointerSize == 4 || PointerSize == 8) && - "Add support for other sizes if necessary"); - // Based on GCC's support for TLS: - if (!DD->useSplitDwarf()) { - // 1) Start with a constNu of the appropriate pointer size - addUInt(*Loc, dwarf::DW_FORM_data1, - PointerSize == 4 ? dwarf::DW_OP_const4u : dwarf::DW_OP_const8u); - // 2) containing the (relocated) offset of the TLS variable - // within the module's TLS block. - addExpr(*Loc, dwarf::DW_FORM_udata, - Asm->getObjFileLowering().getDebugThreadLocalSymbol(Sym)); - } else { - addUInt(*Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_GNU_const_index); - addUInt(*Loc, dwarf::DW_FORM_udata, - DD->getAddressPool().getIndex(Sym, /* TLS */ true)); - } - // 3) followed by a custom OP to make the debugger do a TLS lookup. - addUInt(*Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_GNU_push_tls_address); - } else { - DD->addArangeLabel(SymbolCU(this, Sym)); - addOpAddress(*Loc, Sym); - } - // A static member's declaration is already flagged as such. - if (!SDMDecl.Verify() && !GV.isDefinition()) - addFlag(*VariableDIE, dwarf::DW_AT_declaration); - // Do not create specification DIE if context is either compile unit - // or a subprogram. - if (GVContext && GV.isDefinition() && !GVContext.isCompileUnit() && - !GVContext.isFile() && !DD->isSubprogramContext(GVContext)) { - // Create specification DIE. - VariableSpecDIE = &createAndAddDIE(dwarf::DW_TAG_variable, UnitDie); - addDIEEntry(*VariableSpecDIE, dwarf::DW_AT_specification, *VariableDIE); - addBlock(*VariableSpecDIE, dwarf::DW_AT_location, Loc); - // A static member's declaration is already flagged as such. - if (!SDMDecl.Verify()) - addFlag(*VariableDIE, dwarf::DW_AT_declaration); - } else { - addBlock(*VariableDIE, dwarf::DW_AT_location, Loc); - } - // Add the linkage name. - StringRef LinkageName = GV.getLinkageName(); - if (!LinkageName.empty()) - // From DWARF4: DIEs to which DW_AT_linkage_name may apply include: - // TAG_common_block, TAG_constant, TAG_entry_point, TAG_subprogram and - // TAG_variable. - addString(IsStaticMember && VariableSpecDIE ? *VariableSpecDIE - : *VariableDIE, - DD->getDwarfVersion() >= 4 ? dwarf::DW_AT_linkage_name - : dwarf::DW_AT_MIPS_linkage_name, - GlobalValue::getRealLinkageName(LinkageName)); - } else if (const ConstantInt *CI = - dyn_cast_or_null(GV.getConstant())) { - // AT_const_value was added when the static member was created. To avoid - // emitting AT_const_value multiple times, we only add AT_const_value when - // it is not a static member. - if (!IsStaticMember) - addConstantValue(*VariableDIE, CI, GTy); - } else if (const ConstantExpr *CE = getMergedGlobalExpr(GV.getConstant())) { - addToAccelTable = true; - // GV is a merged global. - DIELoc *Loc = new (DIEValueAllocator) DIELoc(); - Value *Ptr = CE->getOperand(0); - MCSymbol *Sym = Asm->getSymbol(cast(Ptr)); - DD->addArangeLabel(SymbolCU(this, Sym)); - addOpAddress(*Loc, Sym); - addUInt(*Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_constu); - SmallVector Idx(CE->op_begin() + 1, CE->op_end()); - addUInt(*Loc, dwarf::DW_FORM_udata, - Asm->getDataLayout().getIndexedOffset(Ptr->getType(), Idx)); - addUInt(*Loc, dwarf::DW_FORM_data1, dwarf::DW_OP_plus); - addBlock(*VariableDIE, dwarf::DW_AT_location, Loc); - } - - DIE *ResultDIE = VariableSpecDIE ? VariableSpecDIE : VariableDIE; - - if (addToAccelTable) { - DD->addAccelName(GV.getName(), *ResultDIE); - - // If the linkage name is different than the name, go ahead and output - // that as well into the name table. - if (GV.getLinkageName() != "" && GV.getName() != GV.getLinkageName()) - DD->addAccelName(GV.getLinkageName(), *ResultDIE); - } - - addGlobalName(GV.getName(), *ResultDIE, GV.getContext()); - return ResultDIE; -} - /// constructSubrangeDIE - Construct subrange DIE from DISubrange. void DwarfUnit::constructSubrangeDIE(DIE &Buffer, DISubrange SR, DIE *IndexTy) { DIE &DW_Subrange = createAndAddDIE(dwarf::DW_TAG_subrange_type, Buffer); @@ -2049,48 +1829,6 @@ void DwarfUnit::emitHeader(const MCSymbol *ASectionSym) const { Asm->EmitInt8(Asm->getDataLayout().getPointerSize()); } -void DwarfCompileUnit::addRange(RangeSpan Range) { - bool SameAsPrevCU = this == DD->getPrevCU(); - DD->setPrevCU(this); - // If we have no current ranges just add the range and return, otherwise, - // check the current section and CU against the previous section and CU we - // emitted into and the subprogram was contained within. If these are the - // same then extend our current range, otherwise add this as a new range. - if (CURanges.empty() || !SameAsPrevCU || - (&CURanges.back().getEnd()->getSection() != - &Range.getEnd()->getSection())) { - CURanges.push_back(Range); - return; - } - - CURanges.back().setEnd(Range.getEnd()); -} - -void DwarfCompileUnit::initStmtList(MCSymbol *DwarfLineSectionSym) { - // Define start line table label for each Compile Unit. - MCSymbol *LineTableStartSym = - Asm->OutStreamer.getDwarfLineTableSymbol(getUniqueID()); - - stmtListIndex = UnitDie.getValues().size(); - - // DW_AT_stmt_list is a offset of line number information for this - // compile unit in debug_line section. For split dwarf this is - // left in the skeleton CU and so not included. - // The line table entries are not always emitted in assembly, so it - // is not okay to use line_table_start here. - if (Asm->MAI->doesDwarfUseRelocationsAcrossSections()) - addSectionLabel(UnitDie, dwarf::DW_AT_stmt_list, LineTableStartSym); - else - addSectionDelta(UnitDie, dwarf::DW_AT_stmt_list, LineTableStartSym, - DwarfLineSectionSym); -} - -void DwarfCompileUnit::applyStmtList(DIE &D) { - D.addValue(dwarf::DW_AT_stmt_list, - UnitDie.getAbbrev().getData()[stmtListIndex].getForm(), - UnitDie.getValues()[stmtListIndex]); -} - void DwarfTypeUnit::emitHeader(const MCSymbol *ASectionSym) const { DwarfUnit::emitHeader(ASectionSym); Asm->OutStreamer.AddComment("Type Signature"); diff --git a/lib/CodeGen/AsmPrinter/DwarfUnit.h b/lib/CodeGen/AsmPrinter/DwarfUnit.h index c2026cf0032..ff4cf0218ab 100644 --- a/lib/CodeGen/AsmPrinter/DwarfUnit.h +++ b/lib/CodeGen/AsmPrinter/DwarfUnit.h @@ -522,41 +522,6 @@ private: void updateAcceleratorTables(DIScope Context, DIType Ty, const DIE &TyDIE); }; -class DwarfCompileUnit : public DwarfUnit { - /// The attribute index of DW_AT_stmt_list in the compile unit DIE, avoiding - /// the need to search for it in applyStmtList. - unsigned stmtListIndex; - -public: - DwarfCompileUnit(unsigned UID, DICompileUnit Node, AsmPrinter *A, - DwarfDebug *DW, DwarfFile *DWU); - - void initStmtList(MCSymbol *DwarfLineSectionSym); - - /// Apply the DW_AT_stmt_list from this compile unit to the specified DIE. - void applyStmtList(DIE &D); - - /// getOrCreateGlobalVariableDIE - get or create global variable DIE. - DIE *getOrCreateGlobalVariableDIE(DIGlobalVariable GV); - - /// addLabelAddress - Add a dwarf label attribute data and value using - /// either DW_FORM_addr or DW_FORM_GNU_addr_index. - void addLabelAddress(DIE &Die, dwarf::Attribute Attribute, - const MCSymbol *Label); - - /// addLocalLabelAddress - Add a dwarf label attribute data and value using - /// DW_FORM_addr only. - void addLocalLabelAddress(DIE &Die, dwarf::Attribute Attribute, - const MCSymbol *Label); - - DwarfCompileUnit &getCU() override { return *this; } - - unsigned getOrCreateSourceID(StringRef FileName, StringRef DirName) override; - - /// addRange - Add an address range to the list of ranges for this unit. - void addRange(RangeSpan Range); -}; - class DwarfTypeUnit : public DwarfUnit { private: uint64_t TypeSignature;