1321369Sdim//===- DWARFDie.h -----------------------------------------------*- C++ -*-===// 2311116Sdim// 3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353358Sdim// See https://llvm.org/LICENSE.txt for license information. 5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6311116Sdim// 7311116Sdim//===----------------------------------------------------------------------===// 8311116Sdim 9321369Sdim#ifndef LLVM_DEBUGINFO_DWARFDIE_H 10321369Sdim#define LLVM_DEBUGINFO_DWARFDIE_H 11311116Sdim 12321369Sdim#include "llvm/ADT/ArrayRef.h" 13321369Sdim#include "llvm/ADT/Optional.h" 14311544Sdim#include "llvm/ADT/iterator.h" 15311544Sdim#include "llvm/ADT/iterator_range.h" 16321369Sdim#include "llvm/BinaryFormat/Dwarf.h" 17321369Sdim#include "llvm/DebugInfo/DIContext.h" 18341825Sdim#include "llvm/DebugInfo/DWARF/DWARFAddressRange.h" 19321369Sdim#include "llvm/DebugInfo/DWARF/DWARFAttribute.h" 20311116Sdim#include "llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h" 21360784Sdim#include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h" 22321369Sdim#include <cassert> 23321369Sdim#include <cstdint> 24321369Sdim#include <iterator> 25311116Sdim 26311116Sdimnamespace llvm { 27321369Sdim 28311116Sdimclass DWARFUnit; 29311116Sdimclass raw_ostream; 30321369Sdim 31311116Sdim//===----------------------------------------------------------------------===// 32311116Sdim/// Utility class that carries the DWARF compile/type unit and the debug info 33311116Sdim/// entry in an object. 34311116Sdim/// 35311116Sdim/// When accessing information from a debug info entry we always need to DWARF 36311116Sdim/// compile/type unit in order to extract the info correctly as some information 37311116Sdim/// is relative to the compile/type unit. Prior to this class the DWARFUnit and 38311116Sdim/// the DWARFDebugInfoEntry was passed around separately and there was the 39311116Sdim/// possibility for error if the wrong DWARFUnit was used to extract a unit 40311116Sdim/// relative offset. This class helps to ensure that this doesn't happen and 41311116Sdim/// also simplifies the attribute extraction calls by not having to specify the 42311116Sdim/// DWARFUnit for each call. 43311116Sdimclass DWARFDie { 44321369Sdim DWARFUnit *U = nullptr; 45321369Sdim const DWARFDebugInfoEntry *Die = nullptr; 46321369Sdim 47311116Sdimpublic: 48321369Sdim DWARFDie() = default; 49341825Sdim DWARFDie(DWARFUnit *Unit, const DWARFDebugInfoEntry *D) : U(Unit), Die(D) {} 50321369Sdim 51311116Sdim bool isValid() const { return U && Die; } 52311116Sdim explicit operator bool() const { return isValid(); } 53311116Sdim const DWARFDebugInfoEntry *getDebugInfoEntry() const { return Die; } 54311116Sdim DWARFUnit *getDwarfUnit() const { return U; } 55311116Sdim 56311116Sdim /// Get the abbreviation declaration for this DIE. 57311116Sdim /// 58311116Sdim /// \returns the abbreviation declaration or NULL for null tags. 59311116Sdim const DWARFAbbreviationDeclaration *getAbbreviationDeclarationPtr() const { 60311116Sdim assert(isValid() && "must check validity prior to calling"); 61311116Sdim return Die->getAbbreviationDeclarationPtr(); 62311116Sdim } 63311116Sdim 64311116Sdim /// Get the absolute offset into the debug info or types section. 65311116Sdim /// 66311116Sdim /// \returns the DIE offset or -1U if invalid. 67360784Sdim uint64_t getOffset() const { 68311116Sdim assert(isValid() && "must check validity prior to calling"); 69311116Sdim return Die->getOffset(); 70311116Sdim } 71321369Sdim 72311116Sdim dwarf::Tag getTag() const { 73311116Sdim auto AbbrevDecl = getAbbreviationDeclarationPtr(); 74311116Sdim if (AbbrevDecl) 75311116Sdim return AbbrevDecl->getTag(); 76311116Sdim return dwarf::DW_TAG_null; 77311116Sdim } 78311116Sdim 79311116Sdim bool hasChildren() const { 80311116Sdim assert(isValid() && "must check validity prior to calling"); 81311116Sdim return Die->hasChildren(); 82311116Sdim } 83321369Sdim 84311116Sdim /// Returns true for a valid DIE that terminates a sibling chain. 85341825Sdim bool isNULL() const { return getAbbreviationDeclarationPtr() == nullptr; } 86321369Sdim 87311116Sdim /// Returns true if DIE represents a subprogram (not inlined). 88311116Sdim bool isSubprogramDIE() const; 89311116Sdim 90311116Sdim /// Returns true if DIE represents a subprogram or an inlined subroutine. 91311116Sdim bool isSubroutineDIE() const; 92311116Sdim 93311116Sdim /// Get the parent of this DIE object. 94311116Sdim /// 95311116Sdim /// \returns a valid DWARFDie instance if this object has a parent or an 96311116Sdim /// invalid DWARFDie instance if it doesn't. 97311116Sdim DWARFDie getParent() const; 98321369Sdim 99311116Sdim /// Get the sibling of this DIE object. 100311116Sdim /// 101311116Sdim /// \returns a valid DWARFDie instance if this object has a sibling or an 102311116Sdim /// invalid DWARFDie instance if it doesn't. 103311116Sdim DWARFDie getSibling() const; 104321369Sdim 105341825Sdim /// Get the previous sibling of this DIE object. 106341825Sdim /// 107341825Sdim /// \returns a valid DWARFDie instance if this object has a sibling or an 108341825Sdim /// invalid DWARFDie instance if it doesn't. 109341825Sdim DWARFDie getPreviousSibling() const; 110341825Sdim 111311116Sdim /// Get the first child of this DIE object. 112311116Sdim /// 113311116Sdim /// \returns a valid DWARFDie instance if this object has children or an 114311116Sdim /// invalid DWARFDie instance if it doesn't. 115327952Sdim DWARFDie getFirstChild() const; 116321369Sdim 117341825Sdim /// Get the last child of this DIE object. 118341825Sdim /// 119341825Sdim /// \returns a valid null DWARFDie instance if this object has children or an 120341825Sdim /// invalid DWARFDie instance if it doesn't. 121341825Sdim DWARFDie getLastChild() const; 122341825Sdim 123311116Sdim /// Dump the DIE and all of its attributes to the supplied stream. 124311116Sdim /// 125311116Sdim /// \param OS the stream to use for output. 126311116Sdim /// \param indent the number of characters to indent each line that is output. 127327952Sdim void dump(raw_ostream &OS, unsigned indent = 0, 128321369Sdim DIDumpOptions DumpOpts = DIDumpOptions()) const; 129321369Sdim 130327952Sdim /// Convenience zero-argument overload for debugging. 131327952Sdim LLVM_DUMP_METHOD void dump() const; 132327952Sdim 133311116Sdim /// Extract the specified attribute from this DIE. 134311116Sdim /// 135311116Sdim /// Extract an attribute value from this DIE only. This call doesn't look 136311116Sdim /// for the attribute value in any DW_AT_specification or 137311116Sdim /// DW_AT_abstract_origin referenced DIEs. 138311116Sdim /// 139311116Sdim /// \param Attr the attribute to extract. 140311116Sdim /// \returns an optional DWARFFormValue that will have the form value if the 141311116Sdim /// attribute was successfully extracted. 142321369Sdim Optional<DWARFFormValue> find(dwarf::Attribute Attr) const; 143321369Sdim 144321369Sdim /// Extract the first value of any attribute in Attrs from this DIE. 145311116Sdim /// 146321369Sdim /// Extract the first attribute that matches from this DIE only. This call 147321369Sdim /// doesn't look for the attribute value in any DW_AT_specification or 148321369Sdim /// DW_AT_abstract_origin referenced DIEs. The attributes will be searched 149321369Sdim /// linearly in the order they are specified within Attrs. 150311116Sdim /// 151321369Sdim /// \param Attrs an array of DWARF attribute to look for. 152321369Sdim /// \returns an optional that has a valid DWARFFormValue for the first 153321369Sdim /// matching attribute in Attrs, or None if none of the attributes in Attrs 154321369Sdim /// exist in this DIE. 155321369Sdim Optional<DWARFFormValue> find(ArrayRef<dwarf::Attribute> Attrs) const; 156321369Sdim 157321369Sdim /// Extract the first value of any attribute in Attrs from this DIE and 158321369Sdim /// recurse into any DW_AT_specification or DW_AT_abstract_origin referenced 159321369Sdim /// DIEs. 160311116Sdim /// 161321369Sdim /// \param Attrs an array of DWARF attribute to look for. 162321369Sdim /// \returns an optional that has a valid DWARFFormValue for the first 163321369Sdim /// matching attribute in Attrs, or None if none of the attributes in Attrs 164321369Sdim /// exist in this DIE or in any DW_AT_specification or DW_AT_abstract_origin 165321369Sdim /// DIEs. 166321369Sdim Optional<DWARFFormValue> 167321369Sdim findRecursively(ArrayRef<dwarf::Attribute> Attrs) const; 168311116Sdim 169311116Sdim /// Extract the specified attribute from this DIE as the referenced DIE. 170311116Sdim /// 171311116Sdim /// Regardless of the reference type, return the correct DWARFDie instance if 172311116Sdim /// the attribute exists. The returned DWARFDie object might be from another 173311116Sdim /// DWARFUnit, but that is all encapsulated in the new DWARFDie object. 174311116Sdim /// 175311116Sdim /// Extract an attribute value from this DIE only. This call doesn't look 176311116Sdim /// for the attribute value in any DW_AT_specification or 177311116Sdim /// DW_AT_abstract_origin referenced DIEs. 178311116Sdim /// 179311116Sdim /// \param Attr the attribute to extract. 180311116Sdim /// \returns a valid DWARFDie instance if the attribute exists, or an invalid 181311116Sdim /// DWARFDie object if it doesn't. 182311116Sdim DWARFDie getAttributeValueAsReferencedDie(dwarf::Attribute Attr) const; 183344779Sdim DWARFDie getAttributeValueAsReferencedDie(const DWARFFormValue &V) const; 184311116Sdim 185311116Sdim /// Extract the range base attribute from this DIE as absolute section offset. 186311116Sdim /// 187311116Sdim /// This is a utility function that checks for either the DW_AT_rnglists_base 188311116Sdim /// or DW_AT_GNU_ranges_base attribute. 189311116Sdim /// 190311116Sdim /// \returns anm optional absolute section offset value for the attribute. 191311116Sdim Optional<uint64_t> getRangesBaseAttribute() const; 192360784Sdim Optional<uint64_t> getLocBaseAttribute() const; 193321369Sdim 194311116Sdim /// Get the DW_AT_high_pc attribute value as an address. 195311116Sdim /// 196311116Sdim /// In DWARF version 4 and later the high PC can be encoded as an offset from 197311116Sdim /// the DW_AT_low_pc. This function takes care of extracting the value as an 198311116Sdim /// address or offset and adds it to the low PC if needed and returns the 199311116Sdim /// value as an optional in case the DIE doesn't have a DW_AT_high_pc 200311116Sdim /// attribute. 201311116Sdim /// 202311116Sdim /// \param LowPC the low PC that might be needed to calculate the high PC. 203311116Sdim /// \returns an optional address value for the attribute. 204311116Sdim Optional<uint64_t> getHighPC(uint64_t LowPC) const; 205311116Sdim 206311116Sdim /// Retrieves DW_AT_low_pc and DW_AT_high_pc from CU. 207311116Sdim /// Returns true if both attributes are present. 208321369Sdim bool getLowAndHighPC(uint64_t &LowPC, uint64_t &HighPC, 209321369Sdim uint64_t &SectionIndex) const; 210321369Sdim 211311116Sdim /// Get the address ranges for this DIE. 212311116Sdim /// 213311116Sdim /// Get the hi/low PC range if both attributes are available or exrtracts the 214311116Sdim /// non-contiguous address ranges from the DW_AT_ranges attribute. 215311116Sdim /// 216311116Sdim /// Extracts the range information from this DIE only. This call doesn't look 217311116Sdim /// for the range in any DW_AT_specification or DW_AT_abstract_origin DIEs. 218311116Sdim /// 219311116Sdim /// \returns a address range vector that might be empty if no address range 220311116Sdim /// information is available. 221341825Sdim Expected<DWARFAddressRangesVector> getAddressRanges() const; 222321369Sdim 223311116Sdim /// Get all address ranges for any DW_TAG_subprogram DIEs in this DIE or any 224311116Sdim /// of its children. 225311116Sdim /// 226311116Sdim /// Get the hi/low PC range if both attributes are available or exrtracts the 227311116Sdim /// non-contiguous address ranges from the DW_AT_ranges attribute for this DIE 228311116Sdim /// and all children. 229311116Sdim /// 230311116Sdim /// \param Ranges the addres range vector to fill in. 231311116Sdim void collectChildrenAddressRanges(DWARFAddressRangesVector &Ranges) const; 232321369Sdim 233311116Sdim bool addressRangeContainsAddress(const uint64_t Address) const; 234321369Sdim 235360784Sdim Expected<DWARFLocationExpressionsVector> 236360784Sdim getLocations(dwarf::Attribute Attr) const; 237360784Sdim 238311116Sdim /// If a DIE represents a subprogram (or inlined subroutine), returns its 239311116Sdim /// mangled name (or short name, if mangled is missing). This name may be 240311116Sdim /// fetched from specification or abstract origin for this subprogram. 241311116Sdim /// Returns null if no name is found. 242311116Sdim const char *getSubroutineName(DINameKind Kind) const; 243321369Sdim 244311116Sdim /// Return the DIE name resolving DW_AT_sepcification or DW_AT_abstract_origin 245311116Sdim /// references if necessary. Returns null if no name is found. 246311116Sdim const char *getName(DINameKind Kind) const; 247321369Sdim 248321369Sdim /// Returns the declaration line (start line) for a DIE, assuming it specifies 249321369Sdim /// a subprogram. This may be fetched from specification or abstract origin 250321369Sdim /// for this subprogram by resolving DW_AT_sepcification or 251321369Sdim /// DW_AT_abstract_origin references if necessary. 252321369Sdim uint64_t getDeclLine() const; 253321369Sdim 254311116Sdim /// Retrieves values of DW_AT_call_file, DW_AT_call_line and DW_AT_call_column 255311116Sdim /// from DIE (or zeroes if they are missing). This function looks for 256311116Sdim /// DW_AT_call attributes in this DIE only, it will not resolve the attribute 257311116Sdim /// values in any DW_AT_specification or DW_AT_abstract_origin DIEs. 258311116Sdim /// \param CallFile filled in with non-zero if successful, zero if there is no 259311116Sdim /// DW_AT_call_file attribute in this DIE. 260311116Sdim /// \param CallLine filled in with non-zero if successful, zero if there is no 261311116Sdim /// DW_AT_call_line attribute in this DIE. 262311116Sdim /// \param CallColumn filled in with non-zero if successful, zero if there is 263311116Sdim /// no DW_AT_call_column attribute in this DIE. 264321369Sdim /// \param CallDiscriminator filled in with non-zero if successful, zero if 265321369Sdim /// there is no DW_AT_GNU_discriminator attribute in this DIE. 266311116Sdim void getCallerFrame(uint32_t &CallFile, uint32_t &CallLine, 267321369Sdim uint32_t &CallColumn, uint32_t &CallDiscriminator) const; 268311116Sdim 269321369Sdim class attribute_iterator; 270321369Sdim 271321369Sdim /// Get an iterator range to all attributes in the current DIE only. 272321369Sdim /// 273321369Sdim /// \returns an iterator range for the attributes of the current DIE. 274321369Sdim iterator_range<attribute_iterator> attributes() const; 275321369Sdim 276311544Sdim class iterator; 277321369Sdim 278311544Sdim iterator begin() const; 279311544Sdim iterator end() const; 280341825Sdim 281341825Sdim std::reverse_iterator<iterator> rbegin() const; 282341825Sdim std::reverse_iterator<iterator> rend() const; 283341825Sdim 284311544Sdim iterator_range<iterator> children() const; 285311116Sdim}; 286311116Sdim 287341825Sdimclass DWARFDie::attribute_iterator 288341825Sdim : public iterator_facade_base<attribute_iterator, std::forward_iterator_tag, 289341825Sdim const DWARFAttribute> { 290321369Sdim /// The DWARF DIE we are extracting attributes from. 291321369Sdim DWARFDie Die; 292321369Sdim /// The value vended to clients via the operator*() or operator->(). 293321369Sdim DWARFAttribute AttrValue; 294321369Sdim /// The attribute index within the abbreviation declaration in Die. 295321369Sdim uint32_t Index; 296321369Sdim 297341825Sdim friend bool operator==(const attribute_iterator &LHS, 298341825Sdim const attribute_iterator &RHS); 299341825Sdim 300321369Sdim /// Update the attribute index and attempt to read the attribute value. If the 301321369Sdim /// attribute is able to be read, update AttrValue and the Index member 302321369Sdim /// variable. If the attribute value is not able to be read, an appropriate 303321369Sdim /// error will be set if the Err member variable is non-NULL and the iterator 304321369Sdim /// will be set to the end value so iteration stops. 305321369Sdim void updateForIndex(const DWARFAbbreviationDeclaration &AbbrDecl, uint32_t I); 306321369Sdim 307321369Sdimpublic: 308321369Sdim attribute_iterator() = delete; 309321369Sdim explicit attribute_iterator(DWARFDie D, bool End); 310321369Sdim 311321369Sdim attribute_iterator &operator++(); 312341825Sdim attribute_iterator &operator--(); 313321369Sdim explicit operator bool() const { return AttrValue.isValid(); } 314321369Sdim const DWARFAttribute &operator*() const { return AttrValue; } 315321369Sdim}; 316321369Sdim 317341825Sdiminline bool operator==(const DWARFDie::attribute_iterator &LHS, 318341825Sdim const DWARFDie::attribute_iterator &RHS) { 319341825Sdim return LHS.Index == RHS.Index; 320341825Sdim} 321341825Sdim 322341825Sdiminline bool operator!=(const DWARFDie::attribute_iterator &LHS, 323341825Sdim const DWARFDie::attribute_iterator &RHS) { 324341825Sdim return !(LHS == RHS); 325341825Sdim} 326341825Sdim 327311544Sdiminline bool operator==(const DWARFDie &LHS, const DWARFDie &RHS) { 328311544Sdim return LHS.getDebugInfoEntry() == RHS.getDebugInfoEntry() && 329341825Sdim LHS.getDwarfUnit() == RHS.getDwarfUnit(); 330311544Sdim} 331311116Sdim 332311544Sdiminline bool operator!=(const DWARFDie &LHS, const DWARFDie &RHS) { 333311544Sdim return !(LHS == RHS); 334311544Sdim} 335311544Sdim 336327952Sdiminline bool operator<(const DWARFDie &LHS, const DWARFDie &RHS) { 337327952Sdim return LHS.getOffset() < RHS.getOffset(); 338327952Sdim} 339327952Sdim 340341825Sdimclass DWARFDie::iterator 341341825Sdim : public iterator_facade_base<iterator, std::bidirectional_iterator_tag, 342341825Sdim const DWARFDie> { 343311544Sdim DWARFDie Die; 344341825Sdim 345341825Sdim friend std::reverse_iterator<llvm::DWARFDie::iterator>; 346341825Sdim friend bool operator==(const DWARFDie::iterator &LHS, 347341825Sdim const DWARFDie::iterator &RHS); 348341825Sdim 349311544Sdimpublic: 350311544Sdim iterator() = default; 351321369Sdim 352341825Sdim explicit iterator(DWARFDie D) : Die(D) {} 353321369Sdim 354311544Sdim iterator &operator++() { 355311544Sdim Die = Die.getSibling(); 356311544Sdim return *this; 357311544Sdim } 358321369Sdim 359341825Sdim iterator &operator--() { 360341825Sdim Die = Die.getPreviousSibling(); 361341825Sdim return *this; 362341825Sdim } 363341825Sdim 364311544Sdim const DWARFDie &operator*() const { return Die; } 365311544Sdim}; 366311544Sdim 367341825Sdiminline bool operator==(const DWARFDie::iterator &LHS, 368341825Sdim const DWARFDie::iterator &RHS) { 369341825Sdim return LHS.Die == RHS.Die; 370341825Sdim} 371341825Sdim 372341825Sdiminline bool operator!=(const DWARFDie::iterator &LHS, 373341825Sdim const DWARFDie::iterator &RHS) { 374341825Sdim return !(LHS == RHS); 375341825Sdim} 376341825Sdim 377311544Sdim// These inline functions must follow the DWARFDie::iterator definition above 378311544Sdim// as they use functions from that class. 379311544Sdiminline DWARFDie::iterator DWARFDie::begin() const { 380311544Sdim return iterator(getFirstChild()); 381311544Sdim} 382311544Sdim 383311544Sdiminline DWARFDie::iterator DWARFDie::end() const { 384341825Sdim return iterator(getLastChild()); 385311544Sdim} 386311544Sdim 387311544Sdiminline iterator_range<DWARFDie::iterator> DWARFDie::children() const { 388311544Sdim return make_range(begin(), end()); 389311544Sdim} 390311544Sdim 391311116Sdim} // end namespace llvm 392311116Sdim 393341825Sdimnamespace std { 394341825Sdim 395341825Sdimtemplate <> 396341825Sdimclass reverse_iterator<llvm::DWARFDie::iterator> 397341825Sdim : public llvm::iterator_facade_base< 398341825Sdim reverse_iterator<llvm::DWARFDie::iterator>, 399341825Sdim bidirectional_iterator_tag, const llvm::DWARFDie> { 400341825Sdim 401341825Sdimprivate: 402341825Sdim llvm::DWARFDie Die; 403341825Sdim bool AtEnd; 404341825Sdim 405341825Sdimpublic: 406341825Sdim reverse_iterator(llvm::DWARFDie::iterator It) 407341825Sdim : Die(It.Die), AtEnd(!It.Die.getPreviousSibling()) { 408341825Sdim if (!AtEnd) 409341825Sdim Die = Die.getPreviousSibling(); 410341825Sdim } 411341825Sdim 412344779Sdim llvm::DWARFDie::iterator base() const { 413344779Sdim return llvm::DWARFDie::iterator(AtEnd ? Die : Die.getSibling()); 414344779Sdim } 415344779Sdim 416341825Sdim reverse_iterator<llvm::DWARFDie::iterator> &operator++() { 417341825Sdim assert(!AtEnd && "Incrementing rend"); 418341825Sdim llvm::DWARFDie D = Die.getPreviousSibling(); 419341825Sdim if (D) 420341825Sdim Die = D; 421341825Sdim else 422341825Sdim AtEnd = true; 423341825Sdim return *this; 424341825Sdim } 425341825Sdim 426341825Sdim reverse_iterator<llvm::DWARFDie::iterator> &operator--() { 427341825Sdim if (AtEnd) { 428341825Sdim AtEnd = false; 429341825Sdim return *this; 430341825Sdim } 431341825Sdim Die = Die.getSibling(); 432341825Sdim assert(!Die.isNULL() && "Decrementing rbegin"); 433341825Sdim return *this; 434341825Sdim } 435341825Sdim 436341825Sdim const llvm::DWARFDie &operator*() const { 437341825Sdim assert(Die.isValid()); 438341825Sdim return Die; 439341825Sdim } 440341825Sdim 441341825Sdim // FIXME: We should be able to specify the equals operator as a friend, but 442341825Sdim // that causes the compiler to think the operator overload is ambiguous 443341825Sdim // with the friend declaration and the actual definition as candidates. 444341825Sdim bool equals(const reverse_iterator<llvm::DWARFDie::iterator> &RHS) const { 445341825Sdim return Die == RHS.Die && AtEnd == RHS.AtEnd; 446341825Sdim } 447341825Sdim}; 448341825Sdim 449341825Sdim} // namespace std 450341825Sdim 451341825Sdimnamespace llvm { 452341825Sdim 453341825Sdiminline bool operator==(const std::reverse_iterator<DWARFDie::iterator> &LHS, 454341825Sdim const std::reverse_iterator<DWARFDie::iterator> &RHS) { 455341825Sdim return LHS.equals(RHS); 456341825Sdim} 457341825Sdim 458341825Sdiminline bool operator!=(const std::reverse_iterator<DWARFDie::iterator> &LHS, 459341825Sdim const std::reverse_iterator<DWARFDie::iterator> &RHS) { 460341825Sdim return !(LHS == RHS); 461341825Sdim} 462341825Sdim 463341825Sdiminline std::reverse_iterator<DWARFDie::iterator> DWARFDie::rbegin() const { 464341825Sdim return llvm::make_reverse_iterator(end()); 465341825Sdim} 466341825Sdim 467341825Sdiminline std::reverse_iterator<DWARFDie::iterator> DWARFDie::rend() const { 468341825Sdim return llvm::make_reverse_iterator(begin()); 469341825Sdim} 470341825Sdim 471341825Sdim} // end namespace llvm 472341825Sdim 473321369Sdim#endif // LLVM_DEBUGINFO_DWARFDIE_H 474