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