[llvm] r291959 - Cleanup how DWARFDie attributes are accessed and decoded.

Greg Clayton via llvm-commits llvm-commits at lists.llvm.org
Fri Jan 13 13:08:19 PST 2017


Author: gclayton
Date: Fri Jan 13 15:08:18 2017
New Revision: 291959

URL: http://llvm.org/viewvc/llvm-project?rev=291959&view=rev
Log:
Cleanup how DWARFDie attributes are accessed and decoded.

Removed all DWARFDie::getAttributeValueAs*() calls.
Renamed:
  Optional<DWARFFormValue> DWARFDie::getAttributeValue(dwarf::Attribute);
To:
  Optional<DWARFFormValue> DWARFDie::find(dwarf::Attribute);
Added:
  Optional<DWARFFormValue> DWARFDie::findRecursively(dwarf::Attribute);
  
All decoding of Optional<DWARFFormValue> values are now done using the dwarf::to*() functions from DWARFFormValue.h:

Old code:
  
  auto DeclLine = DWARFDie.getAttributeValueAsSignedConstant(DW_AT_decl_line).getValueOr(0);
  
New code:

  auto DeclLine = toUnsigned(DWARFDie.find(DW_AT_decl_line), 0);
  
This composition helps us since we can now easily do:

  auto DeclLine = toUnsigned(DWARFDie.findRecursively(DW_AT_decl_line), 0);
  
This allows us to easily find attribute values in the current DIE only (the first new code above) or in any DW_AT_abstract_origin or DW_AT_specification Dies using the line above. Note that the code line length is shorter and more concise.

Differential Revision: https://reviews.llvm.org/D28581


Modified:
    llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFDie.h
    llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFFormValue.h
    llvm/trunk/lib/DebugInfo/DWARF/DWARFContext.cpp
    llvm/trunk/lib/DebugInfo/DWARF/DWARFDie.cpp
    llvm/trunk/lib/DebugInfo/DWARF/DWARFTypeUnit.cpp
    llvm/trunk/lib/DebugInfo/DWARF/DWARFUnit.cpp
    llvm/trunk/tools/dsymutil/DwarfLinker.cpp
    llvm/trunk/tools/obj2yaml/dwarf2yaml.cpp
    llvm/trunk/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp

Modified: llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFDie.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFDie.h?rev=291959&r1=291958&r2=291959&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFDie.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFDie.h Fri Jan 13 15:08:18 2017
@@ -124,76 +124,17 @@ public:
   /// \param Attr the attribute to extract.
   /// \returns an optional DWARFFormValue that will have the form value if the
   /// attribute was successfully extracted.
-  Optional<DWARFFormValue> getAttributeValue(dwarf::Attribute Attr) const;
-  
-  /// Extract the specified attribute from this DIE as a C string.
-  ///
-  /// Extract an attribute value from this DIE only. This call doesn't look
-  /// for the attribute value in any DW_AT_specification or
-  /// DW_AT_abstract_origin referenced DIEs.
-  ///
-  /// \param Attr the attribute to extract.
-  /// \param FailValue the value to return if this DIE doesn't have this
-  /// attribute.
-  /// \returns the NULL terminated C string value owned by the DWARF section
-  /// that contains the string or FailValue if the attribute doesn't exist or
-  /// if the attribute's form isn't a form that describes an string.
-  const char *getAttributeValueAsString(dwarf::Attribute Attr,
-                                        const char *FailValue) const;
-  
-  /// Extract the specified attribute from this DIE as an address.
-  ///
-  /// Extract an attribute value from this DIE only. This call doesn't look
-  /// for the attribute value in any DW_AT_specification or
-  /// DW_AT_abstract_origin referenced DIEs.
-  ///
-  /// \param Attr the attribute to extract.
-  /// \returns an optional value for the attribute.
-  Optional<uint64_t> getAttributeValueAsAddress(dwarf::Attribute Attr) const;
-  
-  /// Extract the specified attribute from this DIE as a signed integer.
-  ///
-  /// Extract an attribute value from this DIE only. This call doesn't look
-  /// for the attribute value in any DW_AT_specification or
-  /// DW_AT_abstract_origin referenced DIEs.
-  ///
-  /// \param Attr the attribute to extract.
-  /// \returns an optional value for the attribute.
-  Optional<int64_t>
-  getAttributeValueAsSignedConstant(dwarf::Attribute Attr) const;
-  
-  /// Extract the specified attribute from this DIE as an unsigned integer.
-  ///
-  /// Extract an attribute value from this DIE only. This call doesn't look
-  /// for the attribute value in any DW_AT_specification or
-  /// DW_AT_abstract_origin referenced DIEs.
-  ///
-  /// \param Attr the attribute to extract.
-  /// \returns an optional value for the attribute.
-  Optional<uint64_t>
-  getAttributeValueAsUnsignedConstant(dwarf::Attribute Attr) const;
+  Optional<DWARFFormValue> find(dwarf::Attribute Attr) const;
 
-  /// Extract the specified attribute from this DIE as absolute DIE Offset.
-  ///
-  /// Extract an attribute value from this DIE only. This call doesn't look
-  /// for the attribute value in any DW_AT_specification or
-  /// DW_AT_abstract_origin referenced DIEs.
-  ///
-  /// \param Attr the attribute to extract.
-  /// \returns an optional value for the attribute.
-  Optional<uint64_t> getAttributeValueAsReference(dwarf::Attribute Attr) const;
   
-  /// Extract the specified attribute from this DIE as absolute section offset.
-  ///
-  /// Extract an attribute value from this DIE only. This call doesn't look
-  /// for the attribute value in any DW_AT_specification or
-  /// DW_AT_abstract_origin referenced DIEs.
+  /// Extract an attribute value from this DIE and recurse into any
+  /// DW_AT_specification or DW_AT_abstract_origin referenced DIEs.
   ///
   /// \param Attr the attribute to extract.
-  /// \returns an optional value for the attribute.
-  Optional<uint64_t>
-  getAttributeValueAsSectionOffset(dwarf::Attribute Attr) const;
-  
+  /// \returns an optional DWARFFormValue that will have the form value if the
+  /// attribute was successfully extracted.
+  Optional<DWARFFormValue> findRecursively(dwarf::Attribute Attr) const;
+
   /// Extract the specified attribute from this DIE as the referenced DIE.
   ///
   /// Regardless of the reference type, return the correct DWARFDie instance if

Modified: llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFFormValue.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFFormValue.h?rev=291959&r1=291958&r2=291959&view=diff
==============================================================================
--- llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFFormValue.h (original)
+++ llvm/trunk/include/llvm/DebugInfo/DWARF/DWARFFormValue.h Fri Jan 13 15:08:18 2017
@@ -10,6 +10,7 @@
 #ifndef LLVM_DEBUGINFO_DWARFFORMVALUE_H
 #define LLVM_DEBUGINFO_DWARFFORMVALUE_H
 
+#include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/Optional.h"
 #include "llvm/Support/DataExtractor.h"
 #include "llvm/Support/Dwarf.h"
@@ -60,6 +61,10 @@ public:
   void setUValue(uint64_t V) { Value.uval = V; }
   void setSValue(int64_t V) { Value.sval = V; }
   void setPValue(const char *V) { Value.cstr = V; }
+  void setBlockValue(const ArrayRef<uint8_t> &Data) {
+    Value.data = Data.data();
+    setUValue(Data.size());
+  }
   bool isFormClass(FormClass FC) const;
   const DWARFUnit *getUnit() const { return U; }
   void dump(raw_ostream &OS) const;
@@ -164,6 +169,153 @@ private:
   void dumpString(raw_ostream &OS) const;
 };
 
+namespace dwarf {
+  /// Take an optional DWARFFormValue and try to extract a string value from it.
+  ///
+  /// \param V and optional DWARFFormValue to attempt to extract the value from.
+  /// \returns an optional value that contains a value if the form value
+  /// was valid and was a string.
+  inline Optional<const char*> toString(const Optional<DWARFFormValue>& V) {
+    if (V)
+      return V->getAsCString();
+    return None;
+  }
+  
+  /// Take an optional DWARFFormValue and extract a string value from it.
+  ///
+  /// \param V and optional DWARFFormValue to attempt to extract the value from.
+  /// \param Default the default value to return in case of failure.
+  /// \returns the string value or Default if the V doesn't have a value or the
+  /// form value's encoding wasn't a string.
+  inline const char*
+  toString(const Optional<DWARFFormValue>& V, const char *Default) {
+    return toString(V).getValueOr(Default);
+  }
+
+  /// Take an optional DWARFFormValue and try to extract an unsigned constant.
+  ///
+  /// \param V and optional DWARFFormValue to attempt to extract the value from.
+  /// \returns an optional value that contains a value if the form value
+  /// was valid and has a unsigned constant form.
+  inline Optional<uint64_t> toUnsigned(const Optional<DWARFFormValue>& V) {
+    if (V)
+      return V->getAsUnsignedConstant();
+    return None;
+  }
+  
+  /// Take an optional DWARFFormValue and extract a unsigned constant.
+  ///
+  /// \param V and optional DWARFFormValue to attempt to extract the value from.
+  /// \param Default the default value to return in case of failure.
+  /// \returns the extracted unsigned value or Default if the V doesn't have a
+  /// value or the form value's encoding wasn't an unsigned constant form.
+  inline uint64_t
+  toUnsigned(const Optional<DWARFFormValue>& V, uint64_t Default) {
+    return toUnsigned(V).getValueOr(Default);
+  }
+  
+  /// Take an optional DWARFFormValue and try to extract an reference.
+  ///
+  /// \param V and optional DWARFFormValue to attempt to extract the value from.
+  /// \returns an optional value that contains a value if the form value
+  /// was valid and has a reference form.
+  inline Optional<uint64_t> toReference(const Optional<DWARFFormValue>& V) {
+    if (V)
+      return V->getAsReference();
+    return None;
+  }
+  
+  /// Take an optional DWARFFormValue and extract a reference.
+  ///
+  /// \param V and optional DWARFFormValue to attempt to extract the value from.
+  /// \param Default the default value to return in case of failure.
+  /// \returns the extracted reference value or Default if the V doesn't have a
+  /// value or the form value's encoding wasn't a reference form.
+  inline uint64_t
+  toReference(const Optional<DWARFFormValue>& V, uint64_t Default) {
+    return toReference(V).getValueOr(Default);
+  }
+  
+  /// Take an optional DWARFFormValue and try to extract an signed constant.
+  ///
+  /// \param V and optional DWARFFormValue to attempt to extract the value from.
+  /// \returns an optional value that contains a value if the form value
+  /// was valid and has a signed constant form.
+  inline Optional<int64_t> toSigned(const Optional<DWARFFormValue>& V) {
+    if (V)
+      return V->getAsSignedConstant();
+    return None;
+  }
+
+  /// Take an optional DWARFFormValue and extract a signed integer.
+  ///
+  /// \param V and optional DWARFFormValue to attempt to extract the value from.
+  /// \param Default the default value to return in case of failure.
+  /// \returns the extracted signed integer value or Default if the V doesn't
+  /// have a value or the form value's encoding wasn't a signed integer form.
+  inline int64_t
+  toSigned(const Optional<DWARFFormValue>& V, int64_t Default) {
+    return toSigned(V).getValueOr(Default);
+  }
+
+  /// Take an optional DWARFFormValue and try to extract an address.
+  ///
+  /// \param V and optional DWARFFormValue to attempt to extract the value from.
+  /// \returns an optional value that contains a value if the form value
+  /// was valid and has a address form.
+  inline Optional<uint64_t> toAddress(const Optional<DWARFFormValue>& V) {
+    if (V)
+      return V->getAsAddress();
+    return None;
+  }
+
+  /// Take an optional DWARFFormValue and extract a address.
+  ///
+  /// \param V and optional DWARFFormValue to attempt to extract the value from.
+  /// \param Default the default value to return in case of failure.
+  /// \returns the extracted address value or Default if the V doesn't have a
+  /// value or the form value's encoding wasn't an address form.
+  inline uint64_t
+  toAddress(const Optional<DWARFFormValue>& V, uint64_t Default) {
+    return toAddress(V).getValueOr(Default);
+  }
+
+  /// Take an optional DWARFFormValue and try to extract an section offset.
+  ///
+  /// \param V and optional DWARFFormValue to attempt to extract the value from.
+  /// \returns an optional value that contains a value if the form value
+  /// was valid and has a section offset form.
+  inline Optional<uint64_t> toSectionOffset(const Optional<DWARFFormValue>& V) {
+    if (V)
+      return V->getAsSectionOffset();
+    return None;
+  }
+
+  /// Take an optional DWARFFormValue and extract a section offset.
+  ///
+  /// \param V and optional DWARFFormValue to attempt to extract the value from.
+  /// \param Default the default value to return in case of failure.
+  /// \returns the extracted section offset value or Default if the V doesn't
+  /// have a value or the form value's encoding wasn't a section offset form.
+  inline uint64_t
+  toSectionOffset(const Optional<DWARFFormValue>& V, uint64_t Default) {
+    return toSectionOffset(V).getValueOr(Default);
+  }
+
+  /// Take an optional DWARFFormValue and try to extract block data.
+  ///
+  /// \param V and optional DWARFFormValue to attempt to extract the value from.
+  /// \returns an optional value that contains a value if the form value
+  /// was valid and has a block form.
+  inline Optional<ArrayRef<uint8_t>>
+  toBlock(const Optional<DWARFFormValue>& V) {
+    if (V)
+      return V->getAsBlock();
+    return None;
+  }
+
+} // end namespace dwarf
+
 }
 
 #endif

Modified: llvm/trunk/lib/DebugInfo/DWARF/DWARFContext.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/DWARF/DWARFContext.cpp?rev=291959&r1=291958&r2=291959&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/DWARF/DWARFContext.cpp (original)
+++ llvm/trunk/lib/DebugInfo/DWARF/DWARFContext.cpp Fri Jan 13 15:08:18 2017
@@ -128,8 +128,7 @@ void DWARFContext::dump(raw_ostream &OS,
       auto CUDIE = CU->getUnitDIE();
       if (!CUDIE)
         continue;
-      if (auto StmtOffset =
-              CUDIE.getAttributeValueAsSectionOffset(DW_AT_stmt_list)) {
+      if (auto StmtOffset = toSectionOffset(CUDIE.find(DW_AT_stmt_list))) {
         DataExtractor lineData(getLineSection().Data, isLittleEndian(),
                                savedAddressByteSize);
         DWARFDebugLine::LineTable LineTable;
@@ -387,7 +386,7 @@ DWARFContext::getLineTableForUnit(DWARFU
   if (!UnitDIE)
     return nullptr;
 
-  auto Offset = UnitDIE.getAttributeValueAsSectionOffset(DW_AT_stmt_list);
+  auto Offset = toSectionOffset(UnitDIE.find(DW_AT_stmt_list));
   if (!Offset)
     return nullptr; // No line table for this compile unit.
 

Modified: llvm/trunk/lib/DebugInfo/DWARF/DWARFDie.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/DWARF/DWARFDie.cpp?rev=291959&r1=291958&r2=291959&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/DWARF/DWARFDie.cpp (original)
+++ llvm/trunk/lib/DebugInfo/DWARF/DWARFDie.cpp Fri Jan 13 15:08:18 2017
@@ -134,7 +134,7 @@ bool DWARFDie::isSubroutineDIE() const {
 }
 
 Optional<DWARFFormValue>
-DWARFDie::getAttributeValue(dwarf::Attribute Attr) const {
+DWARFDie::find(dwarf::Attribute Attr) const {
   if (!isValid())
     return None;
   auto AbbrevDecl = getAbbreviationDeclarationPtr();
@@ -143,54 +143,24 @@ DWARFDie::getAttributeValue(dwarf::Attri
   return None;
 }
 
-const char *DWARFDie::getAttributeValueAsString(dwarf::Attribute Attr,
-                                                const char *FailValue) const {
-  auto FormValue = getAttributeValue(Attr);
-  if (!FormValue)
-    return FailValue;
-  Optional<const char *> Result = FormValue->getAsCString();
-  return Result.hasValue() ? Result.getValue() : FailValue;
-}
-
-Optional<uint64_t>
-DWARFDie::getAttributeValueAsAddress(dwarf::Attribute Attr) const {
-  if (auto FormValue = getAttributeValue(Attr))
-    return FormValue->getAsAddress();
-  return None;
-}
-
-Optional<int64_t>
-DWARFDie::getAttributeValueAsSignedConstant(dwarf::Attribute Attr) const {
-  if (auto FormValue = getAttributeValue(Attr))
-    return FormValue->getAsSignedConstant();
-  return None;
-}
-
-Optional<uint64_t>
-DWARFDie::getAttributeValueAsUnsignedConstant(dwarf::Attribute Attr) const {
-  if (auto FormValue = getAttributeValue(Attr))
-    return FormValue->getAsUnsignedConstant();
-  return None;
-}
-
-Optional<uint64_t>
-DWARFDie::getAttributeValueAsReference(dwarf::Attribute Attr) const {
-  if (auto FormValue = getAttributeValue(Attr))
-    return FormValue->getAsReference();
-  return None;
-}
-
-Optional<uint64_t>
-DWARFDie::getAttributeValueAsSectionOffset(dwarf::Attribute Attr) const {
-  if (auto FormValue = getAttributeValue(Attr))
-    return FormValue->getAsSectionOffset();
+Optional<DWARFFormValue>
+DWARFDie::findRecursively(dwarf::Attribute Attr) const {
+  if (!isValid())
+    return None;
+  if (auto Value = find(Attr))
+    return Value;
+  if (auto Die = getAttributeValueAsReferencedDie(DW_AT_abstract_origin))
+    if (auto Value = Die.find(Attr))
+      return Value;
+  if (auto Die = getAttributeValueAsReferencedDie(DW_AT_specification))
+    if (auto Value = Die.find(Attr))
+      return Value;
   return None;
 }
 
-
 DWARFDie
 DWARFDie::getAttributeValueAsReferencedDie(dwarf::Attribute Attr) const {
-  auto SpecRef = getAttributeValueAsReference(Attr);
+  auto SpecRef = toReference(find(Attr));
   if (SpecRef) {
     auto SpecUnit = U->getUnitSection().getUnitForOffset(*SpecRef);
     if (SpecUnit)
@@ -201,14 +171,14 @@ DWARFDie::getAttributeValueAsReferencedD
 
 Optional<uint64_t>
 DWARFDie::getRangesBaseAttribute() const {
-  auto Result = getAttributeValueAsSectionOffset(DW_AT_rnglists_base);
+  auto Result = toSectionOffset(find(DW_AT_rnglists_base));
   if (Result)
     return Result;
-  return getAttributeValueAsSectionOffset(DW_AT_GNU_ranges_base);
+  return toSectionOffset(find(DW_AT_GNU_ranges_base));
 }
 
 Optional<uint64_t> DWARFDie::getHighPC(uint64_t LowPC) const {
-  if (auto FormValue = getAttributeValue(DW_AT_high_pc)) {
+  if (auto FormValue = find(DW_AT_high_pc)) {
     if (auto Address = FormValue->getAsAddress()) {
       // High PC is an address.
       return Address;
@@ -222,7 +192,7 @@ Optional<uint64_t> DWARFDie::getHighPC(u
 }
 
 bool DWARFDie::getLowAndHighPC(uint64_t &LowPC, uint64_t &HighPC) const {
-  auto LowPcAddr = getAttributeValueAsAddress(DW_AT_low_pc);
+  auto LowPcAddr = toAddress(find(DW_AT_low_pc));
   if (!LowPcAddr)
     return false;
   if (auto HighPcAddr = getHighPC(*LowPcAddr)) {
@@ -243,7 +213,7 @@ DWARFDie::getAddressRanges() const {
     return DWARFAddressRangesVector(1, std::make_pair(LowPC, HighPC));
   }
   // Multiple ranges from .debug_ranges section.
-  auto RangesOffset = getAttributeValueAsSectionOffset(DW_AT_ranges);
+  auto RangesOffset = toSectionOffset(find(DW_AT_ranges));
   if (RangesOffset) {
     DWARFDebugRangeList RangeList;
     if (U->extractRangeList(*RangesOffset, RangeList))
@@ -284,33 +254,25 @@ const char *
 DWARFDie::getName(DINameKind Kind) const {
   if (!isValid() || Kind == DINameKind::None)
     return nullptr;
-  const char *name = nullptr;
   // Try to get mangled name only if it was asked for.
   if (Kind == DINameKind::LinkageName) {
-    if ((name = getAttributeValueAsString(DW_AT_MIPS_linkage_name, nullptr)))
-      return name;
-    if ((name = getAttributeValueAsString(DW_AT_linkage_name, nullptr)))
-      return name;
-  }
-  if ((name = getAttributeValueAsString(DW_AT_name, nullptr)))
-    return name;
-  // Try to get name from specification DIE.
-  DWARFDie SpecDie = getAttributeValueAsReferencedDie(DW_AT_specification);
-  if (SpecDie && (name = SpecDie.getName(Kind)))
-    return name;
-  // Try to get name from abstract origin DIE.
-  DWARFDie AbsDie = getAttributeValueAsReferencedDie(DW_AT_abstract_origin);
-  if (AbsDie && (name = AbsDie.getName(Kind)))
-    return name;
+    if (auto Name = dwarf::toString(findRecursively(DW_AT_MIPS_linkage_name),
+                                    nullptr))
+      return Name;
+    if (auto Name = dwarf::toString(findRecursively(DW_AT_linkage_name),
+                                    nullptr))
+      return Name;
+  }
+  if (auto Name = dwarf::toString(findRecursively(DW_AT_name), nullptr))
+    return Name;
   return nullptr;
 }
 
 void DWARFDie::getCallerFrame(uint32_t &CallFile, uint32_t &CallLine,
                               uint32_t &CallColumn) const {
-  CallFile = getAttributeValueAsUnsignedConstant(DW_AT_call_file).getValueOr(0);
-  CallLine = getAttributeValueAsUnsignedConstant(DW_AT_call_line).getValueOr(0);
-  CallColumn =
-      getAttributeValueAsUnsignedConstant(DW_AT_call_column).getValueOr(0);
+  CallFile = toUnsigned(find(DW_AT_call_file), 0);
+  CallLine = toUnsigned(find(DW_AT_call_line), 0);
+  CallColumn = toUnsigned(find(DW_AT_call_column), 0);
 }
 
 void DWARFDie::dump(raw_ostream &OS, unsigned RecurseDepth,

Modified: llvm/trunk/lib/DebugInfo/DWARF/DWARFTypeUnit.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/DWARF/DWARFTypeUnit.cpp?rev=291959&r1=291958&r2=291959&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/DWARF/DWARFTypeUnit.cpp (original)
+++ llvm/trunk/lib/DebugInfo/DWARF/DWARFTypeUnit.cpp Fri Jan 13 15:08:18 2017
@@ -26,7 +26,7 @@ bool DWARFTypeUnit::extractImpl(DataExtr
 
 void DWARFTypeUnit::dump(raw_ostream &OS, bool SummarizeTypes) {
   DWARFDie TD = getDIEForOffset(TypeOffset + getOffset());
-  const char *Name = TD.getAttributeValueAsString(llvm::dwarf::DW_AT_name, "");
+  const char *Name = TD.getName(DINameKind::ShortName);
 
   if (SummarizeTypes) {
     OS << "name = '" << Name << "'"

Modified: llvm/trunk/lib/DebugInfo/DWARF/DWARFUnit.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/DebugInfo/DWARF/DWARFUnit.cpp?rev=291959&r1=291958&r2=291959&view=diff
==============================================================================
--- llvm/trunk/lib/DebugInfo/DWARF/DWARFUnit.cpp (original)
+++ llvm/trunk/lib/DebugInfo/DWARF/DWARFUnit.cpp Fri Jan 13 15:08:18 2017
@@ -13,6 +13,7 @@
 #include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h"
 #include "llvm/DebugInfo/DWARF/DWARFContext.h"
 #include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h"
+#include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
 #include "llvm/DebugInfo/DWARF/DWARFUnit.h"
 #include "llvm/Object/ObjectFile.h"
 #include "llvm/Support/Casting.h"
@@ -151,11 +152,11 @@ void DWARFUnit::clear() {
 }
 
 const char *DWARFUnit::getCompilationDir() {
-  return getUnitDIE().getAttributeValueAsString(DW_AT_comp_dir, nullptr);
+  return toString(getUnitDIE().find(DW_AT_comp_dir), nullptr);
 }
 
 Optional<uint64_t> DWARFUnit::getDWOId() {
-  return getUnitDIE().getAttributeValueAsUnsignedConstant(DW_AT_GNU_dwo_id);
+  return toUnsigned(getUnitDIE().find(DW_AT_GNU_dwo_id));
 }
 
 void DWARFUnit::extractDIEsToVector(
@@ -225,17 +226,13 @@ size_t DWARFUnit::extractDIEsIfNeeded(bo
   // If CU DIE was just parsed, copy several attribute values from it.
   if (!HasCUDie) {
     DWARFDie UnitDie = getUnitDIE();
-    auto BaseAddr = UnitDie.getAttributeValueAsAddress(DW_AT_low_pc);
+    auto BaseAddr = toAddress(UnitDie.find(DW_AT_low_pc));
     if (!BaseAddr)
-      BaseAddr = UnitDie.getAttributeValueAsAddress(DW_AT_entry_pc);
+      BaseAddr = toAddress(UnitDie.find(DW_AT_entry_pc));
     if (BaseAddr)
       setBaseAddress(*BaseAddr);
-    AddrOffsetSectionBase =
-        UnitDie.getAttributeValueAsSectionOffset(DW_AT_GNU_addr_base)
-            .getValueOr(0);
-    RangeSectionBase =
-        UnitDie.getAttributeValueAsSectionOffset(DW_AT_rnglists_base)
-            .getValueOr(0);
+    AddrOffsetSectionBase = toSectionOffset(UnitDie.find(DW_AT_GNU_addr_base), 0);
+    RangeSectionBase = toSectionOffset(UnitDie.find(DW_AT_rnglists_base), 0);
     // Don't fall back to DW_AT_GNU_ranges_base: it should be ignored for
     // skeleton CU DIE, so that DWARF users not aware of it are not broken.
   }
@@ -266,17 +263,16 @@ bool DWARFUnit::parseDWO() {
   DWARFDie UnitDie = getUnitDIE();
   if (!UnitDie)
     return false;
-  const char *DWOFileName =
-      UnitDie.getAttributeValueAsString(DW_AT_GNU_dwo_name, nullptr);
+  auto DWOFileName = toString(UnitDie.find(DW_AT_GNU_dwo_name));
   if (!DWOFileName)
     return false;
-  const char *CompilationDir =
-      UnitDie.getAttributeValueAsString(DW_AT_comp_dir, nullptr);
+  auto CompilationDir = toString(UnitDie.find(DW_AT_comp_dir));
   SmallString<16> AbsolutePath;
-  if (sys::path::is_relative(DWOFileName) && CompilationDir != nullptr) {
-    sys::path::append(AbsolutePath, CompilationDir);
+  if (sys::path::is_relative(*DWOFileName) && CompilationDir &&
+      *CompilationDir) {
+    sys::path::append(AbsolutePath, *CompilationDir);
   }
-  sys::path::append(AbsolutePath, DWOFileName);
+  sys::path::append(AbsolutePath, *DWOFileName);
   DWO = llvm::make_unique<DWOHolder>(AbsolutePath);
   DWARFUnit *DWOCU = DWO->getUnit();
   // Verify that compile unit in .dwo file is valid.

Modified: llvm/trunk/tools/dsymutil/DwarfLinker.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/dsymutil/DwarfLinker.cpp?rev=291959&r1=291958&r2=291959&view=diff
==============================================================================
--- llvm/trunk/tools/dsymutil/DwarfLinker.cpp (original)
+++ llvm/trunk/tools/dsymutil/DwarfLinker.cpp Fri Jan 13 15:08:18 2017
@@ -205,14 +205,12 @@ public:
     Info.resize(OrigUnit.getNumDIEs());
 
     auto CUDie = OrigUnit.getUnitDIE(false);
-    unsigned Lang =
-        CUDie.getAttributeValueAsUnsignedConstant(dwarf::DW_AT_language)
-            .getValueOr(0);
-    HasODR = CanUseODR && (Lang == dwarf::DW_LANG_C_plus_plus ||
-                           Lang == dwarf::DW_LANG_C_plus_plus_03 ||
-                           Lang == dwarf::DW_LANG_C_plus_plus_11 ||
-                           Lang == dwarf::DW_LANG_C_plus_plus_14 ||
-                           Lang == dwarf::DW_LANG_ObjC_plus_plus);
+    if (auto Lang = dwarf::toUnsigned(CUDie.find(dwarf::DW_AT_language)))
+      HasODR = CanUseODR && (*Lang == dwarf::DW_LANG_C_plus_plus ||
+                             *Lang == dwarf::DW_LANG_C_plus_plus_03 ||
+                             *Lang == dwarf::DW_LANG_C_plus_plus_11 ||
+                             *Lang == dwarf::DW_LANG_C_plus_plus_14 ||
+                             *Lang == dwarf::DW_LANG_ObjC_plus_plus);
   }
 
   DWARFUnit &getOrigUnit() const { return OrigUnit; }
@@ -843,8 +841,7 @@ void DwarfStreamer::emitLocationsForUnit
   DWARFUnit &OrigUnit = Unit.getOrigUnit();
   auto OrigUnitDie = OrigUnit.getUnitDIE(false);
   int64_t UnitPcOffset = 0;
-  auto OrigLowPc = OrigUnitDie.getAttributeValueAsAddress(dwarf::DW_AT_low_pc);
-  if (OrigLowPc)
+  if (auto OrigLowPc = dwarf::toAddress(OrigUnitDie.find(dwarf::DW_AT_low_pc)))
     UnitPcOffset = int64_t(*OrigLowPc) - Unit.getLowPc();
 
   for (const auto &Attr : Attributes) {
@@ -1558,8 +1555,7 @@ PointerIntPair<DeclContext *, 1> DeclCon
     // Do not unique anything inside CU local functions.
     if ((Context.getTag() == dwarf::DW_TAG_namespace ||
          Context.getTag() == dwarf::DW_TAG_compile_unit) &&
-        !DIE.getAttributeValueAsUnsignedConstant(dwarf::DW_AT_external)
-             .getValueOr(0))
+        !dwarf::toUnsigned(DIE.find(dwarf::DW_AT_external), 0))
       return PointerIntPair<DeclContext *, 1>(nullptr);
     LLVM_FALLTHROUGH;
   case dwarf::DW_TAG_member:
@@ -1573,8 +1569,7 @@ PointerIntPair<DeclContext *, 1> DeclCon
     // created on demand. For example implicitely defined constructors
     // are ambiguous because of the way we identify contexts, and they
     // won't be generated everytime everywhere.
-    if (DIE.getAttributeValueAsUnsignedConstant(dwarf::DW_AT_artificial)
-            .getValueOr(0))
+    if (dwarf::toUnsigned(DIE.find(dwarf::DW_AT_artificial), 0))
       return PointerIntPair<DeclContext *, 1>(nullptr);
     break;
   }
@@ -1614,12 +1609,9 @@ PointerIntPair<DeclContext *, 1> DeclCon
     // namespaces, use these additional data points to make the process
     // safer.  This is disabled for clang modules, because forward
     // declarations of module-defined types do not have a file and line.
-    ByteSize = DIE.getAttributeValueAsUnsignedConstant(dwarf::DW_AT_byte_size)
-                   .getValueOr(UINT64_MAX);
+    ByteSize = dwarf::toUnsigned(DIE.find(dwarf::DW_AT_byte_size), UINT64_MAX);
     if (Tag != dwarf::DW_TAG_namespace || !Name) {
-      if (unsigned FileNum =
-              DIE.getAttributeValueAsUnsignedConstant(dwarf::DW_AT_decl_file)
-                  .getValueOr(0)) {
+      if (unsigned FileNum = dwarf::toUnsigned(DIE.find(dwarf::DW_AT_decl_file), 0)) {
         if (const auto *LT = U.getOrigUnit().getContext().getLineTableForUnit(
                 &U.getOrigUnit())) {
           // FIXME: dsymutil-classic compatibility. I'd rather not
@@ -1632,9 +1624,7 @@ PointerIntPair<DeclContext *, 1> DeclCon
           // instead of "" would allow more uniquing, but for now, do
           // it this way to match dsymutil-classic.
           if (LT->hasFileAtIndex(FileNum)) {
-            Line =
-                DIE.getAttributeValueAsUnsignedConstant(dwarf::DW_AT_decl_line)
-                    .getValueOr(0);
+            Line = dwarf::toUnsigned(DIE.find(dwarf::DW_AT_decl_line), 0);
             // Cache the resolved paths, because calling realpath is expansive.
             StringRef ResolvedPath = U.getResolvedPath(FileNum);
             if (!ResolvedPath.empty()) {
@@ -1782,8 +1772,7 @@ static bool analyzeContextInfo(const DWA
   //
   // We treat non-C++ modules like namespaces for this reason.
   if (DIE.getTag() == dwarf::DW_TAG_module && ParentIdx == 0 &&
-      DIE.getAttributeValueAsString(dwarf::DW_AT_name,
-                                    "") != CU.getClangModuleName()) {
+      dwarf::toString(DIE.find(dwarf::DW_AT_name), "") != CU.getClangModuleName()) {
     InImportedModule = true;
   }
 
@@ -1811,8 +1800,7 @@ static bool analyzeContextInfo(const DWA
   // forward declarations.
   Info.Prune &=
       (DIE.getTag() == dwarf::DW_TAG_module) ||
-      DIE.getAttributeValueAsUnsignedConstant(dwarf::DW_AT_declaration)
-          .getValueOr(0);
+      dwarf::toUnsigned(DIE.find(dwarf::DW_AT_declaration), 0);
 
   // Don't prune it if there is no definition for the DIE.
   Info.Prune &= Info.Ctxt && Info.Ctxt->getCanonicalDIEOffset();
@@ -2129,7 +2117,7 @@ unsigned DwarfLinker::shouldKeepSubprogr
   std::tie(LowPcOffset, LowPcEndOffset) =
       getAttributeOffsets(Abbrev, *LowPcIdx, Offset, OrigUnit);
 
-  auto LowPc = DIE.getAttributeValueAsAddress(dwarf::DW_AT_low_pc);
+  auto LowPc = dwarf::toAddress(DIE.find(dwarf::DW_AT_low_pc));
   assert(LowPc.hasValue() && "low_pc attribute is not an address.");
   if (!LowPc ||
       !RelocMgr.hasValidRelocation(LowPcOffset, LowPcEndOffset, MyInfo))
@@ -2746,14 +2734,11 @@ DIE *DwarfLinker::DIECloner::cloneDIE(
     // file might be start address of another function which got moved
     // independantly by the linker). The computation of the actual
     // high_pc value is done in cloneAddressAttribute().
-    AttrInfo.OrigHighPc =
-        InputDIE.getAttributeValueAsAddress(dwarf::DW_AT_high_pc).getValueOr(0);
+    AttrInfo.OrigHighPc = dwarf::toAddress(InputDIE.find(dwarf::DW_AT_high_pc), 0);
     // Also store the low_pc. It might get relocated in an
     // inline_subprogram that happens at the beginning of its
     // inlining function.
-    AttrInfo.OrigLowPc =
-        InputDIE.getAttributeValueAsAddress(dwarf::DW_AT_low_pc)
-            .getValueOr(UINT64_MAX);
+    AttrInfo.OrigLowPc = dwarf::toAddress(InputDIE.find(dwarf::DW_AT_low_pc), UINT64_MAX);
   }
 
   // Reset the Offset to 0 as we will be working on the local copy of
@@ -2872,9 +2857,7 @@ void DwarfLinker::patchRangesForUnit(con
   auto InvalidRange = FunctionRanges.end(), CurrRange = InvalidRange;
   DWARFUnit &OrigUnit = Unit.getOrigUnit();
   auto OrigUnitDie = OrigUnit.getUnitDIE(false);
-  uint64_t OrigLowPc =
-      OrigUnitDie.getAttributeValueAsAddress(dwarf::DW_AT_low_pc)
-          .getValueOr(-1ULL);
+  uint64_t OrigLowPc = dwarf::toAddress(OrigUnitDie.find(dwarf::DW_AT_low_pc), -1ULL);
   // Ranges addresses are based on the unit's low_pc. Compute the
   // offset we need to apply to adapt to the new unit's low_pc.
   int64_t UnitPcOffset = 0;
@@ -2969,7 +2952,7 @@ static void patchStmtList(DIE &Die, DIEI
 void DwarfLinker::patchLineTableForUnit(CompileUnit &Unit,
                                         DWARFContext &OrigDwarf) {
   DWARFDie CUDie = Unit.getOrigUnit().getUnitDIE();
-  auto StmtList = CUDie.getAttributeValueAsSectionOffset(dwarf::DW_AT_stmt_list);
+  auto StmtList = dwarf::toSectionOffset(CUDie.find(dwarf::DW_AT_stmt_list));
   if (!StmtList)
     return;
 
@@ -3201,10 +3184,10 @@ void DwarfLinker::DIECloner::copyAbbrev(
 
 static uint64_t getDwoId(const DWARFDie &CUDie,
                          const DWARFUnit &Unit) {
-  auto DwoId = CUDie.getAttributeValueAsUnsignedConstant(dwarf::DW_AT_dwo_id);
+  auto DwoId = dwarf::toUnsigned(CUDie.find(dwarf::DW_AT_dwo_id));
   if (DwoId)
     return *DwoId;
-  DwoId = CUDie.getAttributeValueAsUnsignedConstant(dwarf::DW_AT_GNU_dwo_id);
+  DwoId = dwarf::toUnsigned(CUDie.find(dwarf::DW_AT_GNU_dwo_id));
   if (DwoId)
     return *DwoId;
   return 0;
@@ -3213,21 +3196,17 @@ static uint64_t getDwoId(const DWARFDie
 bool DwarfLinker::registerModuleReference(
     const DWARFDie &CUDie, const DWARFUnit &Unit,
     DebugMap &ModuleMap, unsigned Indent) {
-  std::string PCMfile =
-      CUDie.getAttributeValueAsString(dwarf::DW_AT_dwo_name, "");
+  std::string PCMfile = dwarf::toString(CUDie.find(dwarf::DW_AT_dwo_name), "");
   if (PCMfile.empty())
-    PCMfile =
-        CUDie.getAttributeValueAsString(dwarf::DW_AT_GNU_dwo_name, "");
+    PCMfile = dwarf::toString(CUDie.find(dwarf::DW_AT_GNU_dwo_name), "");
   if (PCMfile.empty())
     return false;
 
   // Clang module DWARF skeleton CUs abuse this for the path to the module.
-  std::string PCMpath =
-      CUDie.getAttributeValueAsString(dwarf::DW_AT_comp_dir, "");
+  std::string PCMpath = dwarf::toString(CUDie.find(dwarf::DW_AT_comp_dir), "");
   uint64_t DwoId = getDwoId(CUDie, Unit);
 
-  std::string Name =
-      CUDie.getAttributeValueAsString(dwarf::DW_AT_name, "");
+  std::string Name = dwarf::toString(CUDie.find(dwarf::DW_AT_name), "");
   if (Name.empty()) {
     reportWarning("Anonymous module skeleton CU for " + PCMfile);
     return true;

Modified: llvm/trunk/tools/obj2yaml/dwarf2yaml.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/obj2yaml/dwarf2yaml.cpp?rev=291959&r1=291958&r2=291959&view=diff
==============================================================================
--- llvm/trunk/tools/obj2yaml/dwarf2yaml.cpp (original)
+++ llvm/trunk/tools/obj2yaml/dwarf2yaml.cpp Fri Jan 13 15:08:18 2017
@@ -126,7 +126,7 @@ void dumpDebugInfo(DWARFContextInMemory
           DWARFYAML::FormValue NewValue;
           NewValue.Value = 0xDEADBEEFDEADBEEF;
           DWARFDie DIEWrapper(CU.get(), &DIE);
-          auto FormValue = DIEWrapper.getAttributeValue(AttrSpec.Attr);
+          auto FormValue = DIEWrapper.find(AttrSpec.Attr);
           if (!FormValue)
             return;
           auto Form = FormValue.getValue().getForm();
@@ -228,7 +228,7 @@ void dumpDebugLines(DWARFContextInMemory
     if (!CUDIE)
       continue;
     if (auto StmtOffset =
-            CUDIE.getAttributeValueAsSectionOffset(dwarf::DW_AT_stmt_list)) {
+            dwarf::toSectionOffset(CUDIE.find(dwarf::DW_AT_stmt_list))) {
       DWARFYAML::LineTable DebugLines;
       DataExtractor LineData(DCtx.getLineSection().Data, DCtx.isLittleEndian(),
                              CU->getAddressByteSize());

Modified: llvm/trunk/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp?rev=291959&r1=291958&r2=291959&view=diff
==============================================================================
--- llvm/trunk/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp (original)
+++ llvm/trunk/unittests/DebugInfo/DWARF/DWARFDebugInfoTest.cpp Fri Jan 13 15:08:18 2017
@@ -228,8 +228,7 @@ void TestAllForms() {
   //----------------------------------------------------------------------
   // Test address forms
   //----------------------------------------------------------------------
-  EXPECT_EQ(DieDG.getAttributeValueAsAddress(Attr_DW_FORM_addr).getValueOr(0),
-            AddrValue);
+  EXPECT_EQ(AddrValue, toAddress(DieDG.find(Attr_DW_FORM_addr), 0));
 
   //----------------------------------------------------------------------
   // Test block forms
@@ -238,7 +237,7 @@ void TestAllForms() {
   ArrayRef<uint8_t> ExtractedBlockData;
   Optional<ArrayRef<uint8_t>> BlockDataOpt;
 
-  FormValue = DieDG.getAttributeValue(Attr_DW_FORM_block);
+  FormValue = DieDG.find(Attr_DW_FORM_block);
   EXPECT_TRUE((bool)FormValue);
   BlockDataOpt = FormValue->getAsBlock();
   EXPECT_TRUE(BlockDataOpt.hasValue());
@@ -246,7 +245,7 @@ void TestAllForms() {
   EXPECT_EQ(ExtractedBlockData.size(), BlockSize);
   EXPECT_TRUE(memcmp(ExtractedBlockData.data(), BlockData, BlockSize) == 0);
 
-  FormValue = DieDG.getAttributeValue(Attr_DW_FORM_block1);
+  FormValue = DieDG.find(Attr_DW_FORM_block1);
   EXPECT_TRUE((bool)FormValue);
   BlockDataOpt = FormValue->getAsBlock();
   EXPECT_TRUE(BlockDataOpt.hasValue());
@@ -254,7 +253,7 @@ void TestAllForms() {
   EXPECT_EQ(ExtractedBlockData.size(), BlockSize);
   EXPECT_TRUE(memcmp(ExtractedBlockData.data(), BlockData, BlockSize) == 0);
 
-  FormValue = DieDG.getAttributeValue(Attr_DW_FORM_block2);
+  FormValue = DieDG.find(Attr_DW_FORM_block2);
   EXPECT_TRUE((bool)FormValue);
   BlockDataOpt = FormValue->getAsBlock();
   EXPECT_TRUE(BlockDataOpt.hasValue());
@@ -262,7 +261,7 @@ void TestAllForms() {
   EXPECT_EQ(ExtractedBlockData.size(), BlockSize);
   EXPECT_TRUE(memcmp(ExtractedBlockData.data(), BlockData, BlockSize) == 0);
 
-  FormValue = DieDG.getAttributeValue(Attr_DW_FORM_block4);
+  FormValue = DieDG.find(Attr_DW_FORM_block4);
   EXPECT_TRUE((bool)FormValue);
   BlockDataOpt = FormValue->getAsBlock();
   EXPECT_TRUE(BlockDataOpt.hasValue());
@@ -273,100 +272,64 @@ void TestAllForms() {
   //----------------------------------------------------------------------
   // Test data forms
   //----------------------------------------------------------------------
-  EXPECT_EQ(DieDG.getAttributeValueAsUnsignedConstant(Attr_DW_FORM_data1)
-                .getValueOr(0),
-            Data1);
-  EXPECT_EQ(DieDG.getAttributeValueAsUnsignedConstant(Attr_DW_FORM_data2)
-                .getValueOr(0),
-            Data2);
-  EXPECT_EQ(DieDG.getAttributeValueAsUnsignedConstant(Attr_DW_FORM_data4)
-                .getValueOr(0),
-            Data4);
-  EXPECT_EQ(DieDG.getAttributeValueAsUnsignedConstant(Attr_DW_FORM_data8)
-                .getValueOr(0),
-            Data8);
+  EXPECT_EQ(Data1, toUnsigned(DieDG.find(Attr_DW_FORM_data1), 0));
+  EXPECT_EQ(Data2, toUnsigned(DieDG.find(Attr_DW_FORM_data2), 0));
+  EXPECT_EQ(Data4, toUnsigned(DieDG.find(Attr_DW_FORM_data4), 0));
+  EXPECT_EQ(Data8, toUnsigned(DieDG.find(Attr_DW_FORM_data8), 0));
 
   //----------------------------------------------------------------------
   // Test string forms
   //----------------------------------------------------------------------
-  const char *ExtractedStringValue =
-      DieDG.getAttributeValueAsString(Attr_DW_FORM_string, nullptr);
-  EXPECT_TRUE(ExtractedStringValue != nullptr);
-  EXPECT_TRUE(strcmp(StringValue, ExtractedStringValue) == 0);
-
-  const char *ExtractedStrpValue =
-      DieDG.getAttributeValueAsString(Attr_DW_FORM_strp, nullptr);
-  EXPECT_TRUE(ExtractedStrpValue != nullptr);
-  EXPECT_TRUE(strcmp(StrpValue, ExtractedStrpValue) == 0);
+  auto ExtractedStringValue = toString(DieDG.find(Attr_DW_FORM_string));
+  EXPECT_TRUE((bool)ExtractedStringValue);
+  EXPECT_TRUE(strcmp(StringValue, *ExtractedStringValue) == 0);
+
+  auto ExtractedStrpValue = toString(DieDG.find(Attr_DW_FORM_strp));
+  EXPECT_TRUE((bool)ExtractedStrpValue);
+  EXPECT_TRUE(strcmp(StrpValue, *ExtractedStrpValue) == 0);
 
   //----------------------------------------------------------------------
   // Test reference forms
   //----------------------------------------------------------------------
-  EXPECT_EQ(
-      DieDG.getAttributeValueAsReference(Attr_DW_FORM_ref_addr).getValueOr(0),
-      RefAddr);
-  EXPECT_EQ(DieDG.getAttributeValueAsReference(Attr_DW_FORM_ref1).getValueOr(0),
-            Data1);
-  EXPECT_EQ(DieDG.getAttributeValueAsReference(Attr_DW_FORM_ref2).getValueOr(0),
-            Data2);
-  EXPECT_EQ(DieDG.getAttributeValueAsReference(Attr_DW_FORM_ref4).getValueOr(0),
-            Data4);
-  EXPECT_EQ(DieDG.getAttributeValueAsReference(Attr_DW_FORM_ref8).getValueOr(0),
-            Data8);
-  EXPECT_EQ(
-      DieDG.getAttributeValueAsReference(Attr_DW_FORM_ref_sig8).getValueOr(0),
-      Data8_2);
-  EXPECT_EQ(
-      DieDG.getAttributeValueAsReference(Attr_DW_FORM_ref_udata).getValueOr(0),
-      UData[0]);
+  EXPECT_EQ(RefAddr, toReference(DieDG.find(Attr_DW_FORM_ref_addr), 0));
+  EXPECT_EQ(Data1, toReference(DieDG.find(Attr_DW_FORM_ref1), 0));
+  EXPECT_EQ(Data2, toReference(DieDG.find(Attr_DW_FORM_ref2), 0));
+  EXPECT_EQ(Data4, toReference(DieDG.find(Attr_DW_FORM_ref4), 0));
+  EXPECT_EQ(Data8, toReference(DieDG.find(Attr_DW_FORM_ref8), 0));
+  EXPECT_EQ(Data8_2, toReference(DieDG.find(Attr_DW_FORM_ref_sig8), 0));
+  EXPECT_EQ(UData[0], toReference(DieDG.find(Attr_DW_FORM_ref_udata), 0));
 
   //----------------------------------------------------------------------
   // Test flag forms
   //----------------------------------------------------------------------
-  EXPECT_EQ(DieDG.getAttributeValueAsUnsignedConstant(Attr_DW_FORM_flag_true)
-                .getValueOr(0),
-            1ULL);
-  EXPECT_EQ(DieDG.getAttributeValueAsUnsignedConstant(Attr_DW_FORM_flag_false)
-                .getValueOr(1),
-            0ULL);
-  EXPECT_EQ(DieDG.getAttributeValueAsUnsignedConstant(Attr_DW_FORM_flag_present)
-                .getValueOr(0ULL),
-            1ULL);
+  EXPECT_EQ(1ULL, toUnsigned(DieDG.find(Attr_DW_FORM_flag_true), 0));
+  EXPECT_EQ(0ULL, toUnsigned(DieDG.find(Attr_DW_FORM_flag_false), 1));
+  EXPECT_EQ(1ULL, toUnsigned(DieDG.find(Attr_DW_FORM_flag_present), 0));
 
   //----------------------------------------------------------------------
   // Test SLEB128 based forms
   //----------------------------------------------------------------------
-  EXPECT_EQ(
-      DieDG.getAttributeValueAsSignedConstant(Attr_DW_FORM_sdata).getValueOr(0),
-      SData);
+  EXPECT_EQ(SData, toSigned(DieDG.find(Attr_DW_FORM_sdata), 0));
   if (Version >= 5)
-    EXPECT_EQ(
-        DieDG.getAttributeValueAsSignedConstant(Attr_DW_FORM_implicit_const)
-            .getValueOr(0),
-        ICSData);
+    EXPECT_EQ(ICSData, toSigned(DieDG.find(Attr_DW_FORM_implicit_const), 0));
 
   //----------------------------------------------------------------------
   // Test ULEB128 based forms
   //----------------------------------------------------------------------
-  EXPECT_EQ(DieDG.getAttributeValueAsUnsignedConstant(Attr_DW_FORM_udata)
-                .getValueOr(0),
-            UData[0]);
+  EXPECT_EQ(UData[0], toUnsigned(DieDG.find(Attr_DW_FORM_udata), 0));
 
   //----------------------------------------------------------------------
   // Test DWARF32/DWARF64 forms
   //----------------------------------------------------------------------
-  EXPECT_EQ(DieDG.getAttributeValueAsReference(Attr_DW_FORM_GNU_ref_alt)
-                .getValueOr(0),
-            Dwarf32Values[0]);
-  EXPECT_EQ(DieDG.getAttributeValueAsSectionOffset(Attr_DW_FORM_sec_offset)
-                .getValueOr(0),
-            Dwarf32Values[1]);
+  EXPECT_EQ(Dwarf32Values[0],
+            toReference(DieDG.find(Attr_DW_FORM_GNU_ref_alt), 0));
+  EXPECT_EQ(Dwarf32Values[1],
+            toSectionOffset(DieDG.find(Attr_DW_FORM_sec_offset), 0));
 
   //----------------------------------------------------------------------
   // Add an address at the end to make sure we can decode this value
   //----------------------------------------------------------------------
-  EXPECT_EQ(DieDG.getAttributeValueAsAddress(Attr_Last).getValueOr(0),
-            AddrValue);
+  EXPECT_EQ(AddrValue, toAddress(DieDG.find(Attr_Last), 0));
 }
 
 TEST(DWARFDebugInfo, TestDWARF32Version2Addr4AllForms) {
@@ -669,123 +632,107 @@ template <uint16_t Version, class AddrTy
   auto CU1TypeDieDG = Unit1DieDG.getFirstChild();
   EXPECT_TRUE(CU1TypeDieDG.isValid());
   EXPECT_EQ(CU1TypeDieDG.getTag(), DW_TAG_base_type);
-  EXPECT_EQ(CU1TypeDieDG.getAttributeValueAsUnsignedConstant(DW_AT_encoding)
-                .getValueOr(0),
-            DW_ATE_signed);
+  EXPECT_EQ(DW_ATE_signed, toUnsigned(CU1TypeDieDG.find(DW_AT_encoding), 0));
 
   // Verify the first child of the compile unit 2 DIE is our float base type.
   auto CU2TypeDieDG = Unit2DieDG.getFirstChild();
   EXPECT_TRUE(CU2TypeDieDG.isValid());
   EXPECT_EQ(CU2TypeDieDG.getTag(), DW_TAG_base_type);
-  EXPECT_EQ(CU2TypeDieDG.getAttributeValueAsUnsignedConstant(DW_AT_encoding)
-                .getValueOr(0),
-            DW_ATE_float);
+  EXPECT_EQ(DW_ATE_float, toUnsigned(CU2TypeDieDG.find(DW_AT_encoding), 0));
 
   // Verify the sibling of the base type DIE is our Ref1 DIE and that its
   // DW_AT_type points to our base type DIE.
   auto CU1Ref1DieDG = CU1TypeDieDG.getSibling();
   EXPECT_TRUE(CU1Ref1DieDG.isValid());
   EXPECT_EQ(CU1Ref1DieDG.getTag(), DW_TAG_variable);
-  EXPECT_EQ(
-      CU1Ref1DieDG.getAttributeValueAsReference(DW_AT_type).getValueOr(-1ULL),
-      CU1TypeDieDG.getOffset());
+  EXPECT_EQ(CU1TypeDieDG.getOffset(),
+            toReference(CU1Ref1DieDG.find(DW_AT_type), -1ULL));
   // Verify the sibling is our Ref2 DIE and that its DW_AT_type points to our
   // base type DIE in CU1.
   auto CU1Ref2DieDG = CU1Ref1DieDG.getSibling();
   EXPECT_TRUE(CU1Ref2DieDG.isValid());
   EXPECT_EQ(CU1Ref2DieDG.getTag(), DW_TAG_variable);
-  EXPECT_EQ(
-      CU1Ref2DieDG.getAttributeValueAsReference(DW_AT_type).getValueOr(-1ULL),
-      CU1TypeDieDG.getOffset());
+  EXPECT_EQ(CU1TypeDieDG.getOffset(),
+            toReference(CU1Ref2DieDG.find(DW_AT_type), -1ULL));
 
   // Verify the sibling is our Ref4 DIE and that its DW_AT_type points to our
   // base type DIE in CU1.
   auto CU1Ref4DieDG = CU1Ref2DieDG.getSibling();
   EXPECT_TRUE(CU1Ref4DieDG.isValid());
   EXPECT_EQ(CU1Ref4DieDG.getTag(), DW_TAG_variable);
-  EXPECT_EQ(
-      CU1Ref4DieDG.getAttributeValueAsReference(DW_AT_type).getValueOr(-1ULL),
-      CU1TypeDieDG.getOffset());
+  EXPECT_EQ(CU1TypeDieDG.getOffset(),
+            toReference(CU1Ref4DieDG.find(DW_AT_type), -1ULL));
 
   // Verify the sibling is our Ref8 DIE and that its DW_AT_type points to our
   // base type DIE in CU1.
   auto CU1Ref8DieDG = CU1Ref4DieDG.getSibling();
   EXPECT_TRUE(CU1Ref8DieDG.isValid());
   EXPECT_EQ(CU1Ref8DieDG.getTag(), DW_TAG_variable);
-  EXPECT_EQ(
-      CU1Ref8DieDG.getAttributeValueAsReference(DW_AT_type).getValueOr(-1ULL),
-      CU1TypeDieDG.getOffset());
+  EXPECT_EQ(CU1TypeDieDG.getOffset(),
+            toReference(CU1Ref8DieDG.find(DW_AT_type), -1ULL));
 
   // Verify the sibling is our RefAddr DIE and that its DW_AT_type points to our
   // base type DIE in CU1.
   auto CU1RefAddrDieDG = CU1Ref8DieDG.getSibling();
   EXPECT_TRUE(CU1RefAddrDieDG.isValid());
   EXPECT_EQ(CU1RefAddrDieDG.getTag(), DW_TAG_variable);
-  EXPECT_EQ(CU1RefAddrDieDG.getAttributeValueAsReference(DW_AT_type)
-                .getValueOr(-1ULL),
-            CU1TypeDieDG.getOffset());
+  EXPECT_EQ(CU1TypeDieDG.getOffset(),
+            toReference(CU1RefAddrDieDG.find(DW_AT_type), -1ULL));
 
   // Verify the sibling of the Ref4 DIE is our RefAddr DIE and that its
   // DW_AT_type points to our base type DIE.
   auto CU1ToCU2RefAddrDieDG = CU1RefAddrDieDG.getSibling();
   EXPECT_TRUE(CU1ToCU2RefAddrDieDG.isValid());
   EXPECT_EQ(CU1ToCU2RefAddrDieDG.getTag(), DW_TAG_variable);
-  EXPECT_EQ(CU1ToCU2RefAddrDieDG.getAttributeValueAsReference(DW_AT_type)
-                .getValueOr(-1ULL),
-            CU2TypeDieDG.getOffset());
+  EXPECT_EQ(CU2TypeDieDG.getOffset(),
+            toReference(CU1ToCU2RefAddrDieDG.find(DW_AT_type), -1ULL));
 
   // Verify the sibling of the base type DIE is our Ref1 DIE and that its
   // DW_AT_type points to our base type DIE.
   auto CU2Ref1DieDG = CU2TypeDieDG.getSibling();
   EXPECT_TRUE(CU2Ref1DieDG.isValid());
   EXPECT_EQ(CU2Ref1DieDG.getTag(), DW_TAG_variable);
-  EXPECT_EQ(
-      CU2Ref1DieDG.getAttributeValueAsReference(DW_AT_type).getValueOr(-1ULL),
-      CU2TypeDieDG.getOffset());
+  EXPECT_EQ(CU2TypeDieDG.getOffset(),
+            toReference(CU2Ref1DieDG.find(DW_AT_type), -1ULL));
   // Verify the sibling is our Ref2 DIE and that its DW_AT_type points to our
   // base type DIE in CU2.
   auto CU2Ref2DieDG = CU2Ref1DieDG.getSibling();
   EXPECT_TRUE(CU2Ref2DieDG.isValid());
   EXPECT_EQ(CU2Ref2DieDG.getTag(), DW_TAG_variable);
-  EXPECT_EQ(
-      CU2Ref2DieDG.getAttributeValueAsReference(DW_AT_type).getValueOr(-1ULL),
-      CU2TypeDieDG.getOffset());
+  EXPECT_EQ(CU2TypeDieDG.getOffset(),
+            toReference(CU2Ref2DieDG.find(DW_AT_type), -1ULL));
 
   // Verify the sibling is our Ref4 DIE and that its DW_AT_type points to our
   // base type DIE in CU2.
   auto CU2Ref4DieDG = CU2Ref2DieDG.getSibling();
   EXPECT_TRUE(CU2Ref4DieDG.isValid());
   EXPECT_EQ(CU2Ref4DieDG.getTag(), DW_TAG_variable);
-  EXPECT_EQ(
-      CU2Ref4DieDG.getAttributeValueAsReference(DW_AT_type).getValueOr(-1ULL),
-      CU2TypeDieDG.getOffset());
+  EXPECT_EQ(CU2TypeDieDG.getOffset(),
+            toReference(CU2Ref4DieDG.find(DW_AT_type), -1ULL));
 
   // Verify the sibling is our Ref8 DIE and that its DW_AT_type points to our
   // base type DIE in CU2.
   auto CU2Ref8DieDG = CU2Ref4DieDG.getSibling();
   EXPECT_TRUE(CU2Ref8DieDG.isValid());
   EXPECT_EQ(CU2Ref8DieDG.getTag(), DW_TAG_variable);
-  EXPECT_EQ(
-      CU2Ref8DieDG.getAttributeValueAsReference(DW_AT_type).getValueOr(-1ULL),
-      CU2TypeDieDG.getOffset());
+  EXPECT_EQ(CU2TypeDieDG.getOffset(),
+            toReference(CU2Ref8DieDG.find(DW_AT_type), -1ULL));
 
   // Verify the sibling is our RefAddr DIE and that its DW_AT_type points to our
   // base type DIE in CU2.
   auto CU2RefAddrDieDG = CU2Ref8DieDG.getSibling();
   EXPECT_TRUE(CU2RefAddrDieDG.isValid());
   EXPECT_EQ(CU2RefAddrDieDG.getTag(), DW_TAG_variable);
-  EXPECT_EQ(CU2RefAddrDieDG.getAttributeValueAsReference(DW_AT_type)
-                .getValueOr(-1ULL),
-            CU2TypeDieDG.getOffset());
+  EXPECT_EQ(CU2TypeDieDG.getOffset(),
+            toReference(CU2RefAddrDieDG.find(DW_AT_type), -1ULL));
 
   // Verify the sibling of the Ref4 DIE is our RefAddr DIE and that its
   // DW_AT_type points to our base type DIE.
   auto CU2ToCU1RefAddrDieDG = CU2RefAddrDieDG.getSibling();
   EXPECT_TRUE(CU2ToCU1RefAddrDieDG.isValid());
   EXPECT_EQ(CU2ToCU1RefAddrDieDG.getTag(), DW_TAG_variable);
-  EXPECT_EQ(CU2ToCU1RefAddrDieDG.getAttributeValueAsReference(DW_AT_type)
-                .getValueOr(-1ULL),
-            CU1TypeDieDG.getOffset());
+  EXPECT_EQ(CU1TypeDieDG.getOffset(),
+            toReference(CU2ToCU1RefAddrDieDG.find(DW_AT_type), -1ULL));
 }
 
 TEST(DWARFDebugInfo, TestDWARF32Version2Addr4References) {
@@ -892,14 +839,14 @@ template <uint16_t Version, class AddrTy
   auto SubprogramDieNoPC = DieDG.getFirstChild();
   EXPECT_TRUE(SubprogramDieNoPC.isValid());
   EXPECT_EQ(SubprogramDieNoPC.getTag(), DW_TAG_subprogram);
-  OptU64 = SubprogramDieNoPC.getAttributeValueAsAddress(DW_AT_low_pc);
+  OptU64 = toAddress(SubprogramDieNoPC.find(DW_AT_low_pc));
   EXPECT_FALSE((bool)OptU64);
-  OptU64 = SubprogramDieNoPC.getAttributeValueAsAddress(DW_AT_high_pc);
+  OptU64 = toAddress(SubprogramDieNoPC.find(DW_AT_high_pc));
   EXPECT_FALSE((bool)OptU64);
   EXPECT_FALSE(SubprogramDieNoPC.getLowAndHighPC(LowPC, HighPC));
-  OptU64 = SubprogramDieNoPC.getAttributeValueAsAddress(DW_AT_high_pc);
+  OptU64 = toAddress(SubprogramDieNoPC.find(DW_AT_high_pc));
   EXPECT_FALSE((bool)OptU64);
-  OptU64 = SubprogramDieNoPC.getAttributeValueAsUnsignedConstant(DW_AT_high_pc);
+  OptU64 = toUnsigned(SubprogramDieNoPC.find(DW_AT_high_pc));
   EXPECT_FALSE((bool)OptU64);
   OptU64 = SubprogramDieNoPC.getHighPC(ActualLowPC);
   EXPECT_FALSE((bool)OptU64);
@@ -912,12 +859,12 @@ template <uint16_t Version, class AddrTy
   auto SubprogramDieLowPC = SubprogramDieNoPC.getSibling();
   EXPECT_TRUE(SubprogramDieLowPC.isValid());
   EXPECT_EQ(SubprogramDieLowPC.getTag(), DW_TAG_subprogram);
-  OptU64 = SubprogramDieLowPC.getAttributeValueAsAddress(DW_AT_low_pc);
+  OptU64 = toAddress(SubprogramDieLowPC.find(DW_AT_low_pc));
   EXPECT_TRUE((bool)OptU64);
   EXPECT_EQ(OptU64.getValue(), ActualLowPC);
-  OptU64 = SubprogramDieLowPC.getAttributeValueAsAddress(DW_AT_high_pc);
+  OptU64 = toAddress(SubprogramDieLowPC.find(DW_AT_high_pc));
   EXPECT_FALSE((bool)OptU64);
-  OptU64 = SubprogramDieLowPC.getAttributeValueAsUnsignedConstant(DW_AT_high_pc);
+  OptU64 = toUnsigned(SubprogramDieLowPC.find(DW_AT_high_pc));
   EXPECT_FALSE((bool)OptU64);
   OptU64 = SubprogramDieLowPC.getHighPC(ActualLowPC);
   EXPECT_FALSE((bool)OptU64);
@@ -930,12 +877,12 @@ template <uint16_t Version, class AddrTy
   auto SubprogramDieLowHighPC = SubprogramDieLowPC.getSibling();
   EXPECT_TRUE(SubprogramDieLowHighPC.isValid());
   EXPECT_EQ(SubprogramDieLowHighPC.getTag(), DW_TAG_subprogram);
-  OptU64 = SubprogramDieLowHighPC.getAttributeValueAsAddress(DW_AT_low_pc);
+  OptU64 = toAddress(SubprogramDieLowHighPC.find(DW_AT_low_pc));
   EXPECT_TRUE((bool)OptU64);
   EXPECT_EQ(OptU64.getValue(), ActualLowPC);
   // Get the high PC as an address. This should succeed if the high PC was
   // encoded as an address and fail if the high PC was encoded as an offset.
-  OptU64 = SubprogramDieLowHighPC.getAttributeValueAsAddress(DW_AT_high_pc);
+  OptU64 = toAddress(SubprogramDieLowHighPC.find(DW_AT_high_pc));
   if (SupportsHighPCAsOffset) {
     EXPECT_FALSE((bool)OptU64);
   } else {
@@ -944,8 +891,7 @@ template <uint16_t Version, class AddrTy
   }
   // Get the high PC as an unsigned constant. This should succeed if the high PC
   // was encoded as an offset and fail if the high PC was encoded as an address.
-  OptU64 = SubprogramDieLowHighPC.getAttributeValueAsUnsignedConstant(
-      DW_AT_high_pc);
+  OptU64 = toUnsigned(SubprogramDieLowHighPC.find(DW_AT_high_pc));
   if (SupportsHighPCAsOffset) {
     EXPECT_TRUE((bool)OptU64);
     EXPECT_EQ(OptU64.getValue(), ActualHighPCOffset);
@@ -1318,4 +1264,216 @@ TEST(DWARFDebugInfo, TestAttributeIterat
   EXPECT_EQ(E, ++I);
 }
 
+TEST(DWARFDebugInfo, TestFindRecurse) {
+  uint16_t Version = 4;
+  
+  const uint8_t AddrSize = sizeof(void *);
+  initLLVMIfNeeded();
+  Triple Triple = getHostTripleForAddrSize(AddrSize);
+  auto ExpectedDG = dwarfgen::Generator::create(Triple, Version);
+  if (HandleExpectedError(ExpectedDG))
+    return;
+  dwarfgen::Generator *DG = ExpectedDG.get().get();
+  dwarfgen::CompileUnit &CU = DG->addCompileUnit();
+  
+  StringRef SpecDieName("spec");
+  StringRef AbsDieName("abs");
+  // Scope to allow us to re-use the same DIE names
+  {
+    // Create a compile unit DIE that has an abbreviation that says it has
+    // children, but doesn't have any actual attributes. This helps us test
+    // a DIE that has only one child: a NULL DIE.
+    auto CUDie = CU.getUnitDIE();
+    auto FuncSpecDie = CUDie.addChild(DW_TAG_subprogram);
+    auto FuncDie = CUDie.addChild(DW_TAG_subprogram);
+    auto VarAbsDie = CUDie.addChild(DW_TAG_variable);
+    auto VarDie = CUDie.addChild(DW_TAG_variable);
+    FuncSpecDie.addAttribute(DW_AT_name, DW_FORM_strp, SpecDieName);
+    FuncDie.addAttribute(DW_AT_specification, DW_FORM_ref4, FuncSpecDie);
+    VarAbsDie.addAttribute(DW_AT_name, DW_FORM_strp, AbsDieName);
+    VarDie.addAttribute(DW_AT_abstract_origin, DW_FORM_ref4, VarAbsDie);
+  }
+  
+  MemoryBufferRef FileBuffer(DG->generate(), "dwarf");
+  auto Obj = object::ObjectFile::createObjectFile(FileBuffer);
+  EXPECT_TRUE((bool)Obj);
+  DWARFContextInMemory DwarfContext(*Obj.get());
+  
+  // Verify the number of compile units is correct.
+  uint32_t NumCUs = DwarfContext.getNumCompileUnits();
+  EXPECT_EQ(NumCUs, 1u);
+  DWARFCompileUnit *U = DwarfContext.getCompileUnitAtIndex(0);
+  
+  // Get the compile unit DIE is valid.
+  auto CUDie = U->getUnitDIE(false);
+  EXPECT_TRUE(CUDie.isValid());
+  
+  auto FuncSpecDie = CUDie.getFirstChild();
+  auto FuncDie = FuncSpecDie.getSibling();
+  auto VarAbsDie = FuncDie.getSibling();
+  auto VarDie = VarAbsDie.getSibling();
+
+  // Make sure we can't extract the name from the specification die when using
+  // DWARFDie::find() since it won't check the DW_AT_specification DIE.
+  EXPECT_FALSE(FuncDie.find(DW_AT_name).hasValue());
+
+  // Make sure we can extract the name from the specification die when using
+  // DWARFDie::findRecursively() since it should recurse through the
+  // DW_AT_specification DIE.
+  auto NameOpt = FuncDie.findRecursively(DW_AT_name);
+  EXPECT_TRUE(NameOpt.hasValue());
+  // Test the dwarf::toString() helper function.
+  auto StringOpt = toString(NameOpt);
+  EXPECT_TRUE(StringOpt.hasValue());
+  EXPECT_EQ(SpecDieName, StringOpt.getValueOr(nullptr));
+  // Test the dwarf::toString() helper function with a default value specified.
+  EXPECT_EQ(SpecDieName, toString(NameOpt, nullptr));
+  
+  // Make sure we can't extract the name from the abstract origin die when using
+  // DWARFDie::find() since it won't check the DW_AT_abstract_origin DIE.
+  EXPECT_FALSE(VarDie.find(DW_AT_name).hasValue());
+  
+  // Make sure we can extract the name from the abstract origin die when using
+  // DWARFDie::findRecursively() since it should recurse through the
+  // DW_AT_abstract_origin DIE.
+  NameOpt = VarDie.findRecursively(DW_AT_name);
+  EXPECT_TRUE(NameOpt.hasValue());
+  // Test the dwarf::toString() helper function.
+  StringOpt = toString(NameOpt);
+  EXPECT_TRUE(StringOpt.hasValue());
+  EXPECT_EQ(AbsDieName, StringOpt.getValueOr(nullptr));
+  // Test the dwarf::toString() helper function with a default value specified.
+  EXPECT_EQ(AbsDieName, toString(NameOpt, nullptr));
+}
+
+TEST(DWARFDebugInfo, TestDwarfToFunctions) {
+  // Test all of the dwarf::toXXX functions that take a
+  // Optional<DWARFFormValue> and extract the values from it.
+  DWARFFormValue FormVal;
+  uint64_t InvalidU64 = 0xBADBADBADBADBADB;
+  int64_t InvalidS64 = 0xBADBADBADBADBADB;
+  // First test that we don't get valid values back when using an optional with
+  // no value.
+  Optional<DWARFFormValue> FormValOpt;
+  EXPECT_FALSE(toString(FormValOpt).hasValue());
+  EXPECT_FALSE(toUnsigned(FormValOpt).hasValue());
+  EXPECT_FALSE(toReference(FormValOpt).hasValue());
+  EXPECT_FALSE(toSigned(FormValOpt).hasValue());
+  EXPECT_FALSE(toAddress(FormValOpt).hasValue());
+  EXPECT_FALSE(toSectionOffset(FormValOpt).hasValue());
+  EXPECT_FALSE(toBlock(FormValOpt).hasValue());
+  EXPECT_EQ(nullptr, toString(FormValOpt, nullptr));
+  EXPECT_EQ(InvalidU64, toUnsigned(FormValOpt, InvalidU64));
+  EXPECT_EQ(InvalidU64, toReference(FormValOpt, InvalidU64));
+  EXPECT_EQ(InvalidU64, toAddress(FormValOpt, InvalidU64));
+  EXPECT_EQ(InvalidU64, toSectionOffset(FormValOpt, InvalidU64));
+  EXPECT_EQ(InvalidS64, toSigned(FormValOpt, InvalidS64));
+
+  
+  // Test successful and unsuccessful address decoding.
+  uint64_t Address = 0x100000000ULL;
+  FormVal.setForm(DW_FORM_addr);
+  FormVal.setUValue(Address);
+  FormValOpt = FormVal;
+
+  EXPECT_FALSE(toString(FormValOpt).hasValue());
+  EXPECT_FALSE(toUnsigned(FormValOpt).hasValue());
+  EXPECT_FALSE(toReference(FormValOpt).hasValue());
+  EXPECT_FALSE(toSigned(FormValOpt).hasValue());
+  EXPECT_TRUE(toAddress(FormValOpt).hasValue());
+  EXPECT_FALSE(toSectionOffset(FormValOpt).hasValue());
+  EXPECT_FALSE(toBlock(FormValOpt).hasValue());
+  EXPECT_EQ(nullptr, toString(FormValOpt, nullptr));
+  EXPECT_EQ(InvalidU64, toUnsigned(FormValOpt, InvalidU64));
+  EXPECT_EQ(InvalidU64, toReference(FormValOpt, InvalidU64));
+  EXPECT_EQ(Address, toAddress(FormValOpt, InvalidU64));
+  EXPECT_EQ(InvalidU64, toSectionOffset(FormValOpt, InvalidU64));
+  EXPECT_EQ(InvalidS64, toSigned(FormValOpt, InvalidU64));
+
+  // Test successful and unsuccessful unsigned constant decoding.
+  uint64_t UData8 = 0x1020304050607080ULL;
+  FormVal.setForm(DW_FORM_udata);
+  FormVal.setUValue(UData8);
+  FormValOpt = FormVal;
+  
+  EXPECT_FALSE(toString(FormValOpt).hasValue());
+  EXPECT_TRUE(toUnsigned(FormValOpt).hasValue());
+  EXPECT_FALSE(toReference(FormValOpt).hasValue());
+  EXPECT_TRUE(toSigned(FormValOpt).hasValue());
+  EXPECT_FALSE(toAddress(FormValOpt).hasValue());
+  EXPECT_FALSE(toSectionOffset(FormValOpt).hasValue());
+  EXPECT_FALSE(toBlock(FormValOpt).hasValue());
+  EXPECT_EQ(nullptr, toString(FormValOpt, nullptr));
+  EXPECT_EQ(UData8, toUnsigned(FormValOpt, InvalidU64));
+  EXPECT_EQ(InvalidU64, toReference(FormValOpt, InvalidU64));
+  EXPECT_EQ(InvalidU64, toAddress(FormValOpt, InvalidU64));
+  EXPECT_EQ(InvalidU64, toSectionOffset(FormValOpt, InvalidU64));
+  EXPECT_EQ((int64_t)UData8, toSigned(FormValOpt, InvalidU64));
+
+  // Test successful and unsuccessful reference decoding.
+  uint32_t RefData = 0x11223344U;
+  FormVal.setForm(DW_FORM_ref_addr);
+  FormVal.setUValue(RefData);
+  FormValOpt = FormVal;
+  
+  EXPECT_FALSE(toString(FormValOpt).hasValue());
+  EXPECT_FALSE(toUnsigned(FormValOpt).hasValue());
+  EXPECT_TRUE(toReference(FormValOpt).hasValue());
+  EXPECT_FALSE(toSigned(FormValOpt).hasValue());
+  EXPECT_FALSE(toAddress(FormValOpt).hasValue());
+  EXPECT_FALSE(toSectionOffset(FormValOpt).hasValue());
+  EXPECT_FALSE(toBlock(FormValOpt).hasValue());
+  EXPECT_EQ(nullptr, toString(FormValOpt, nullptr));
+  EXPECT_EQ(InvalidU64, toUnsigned(FormValOpt, InvalidU64));
+  EXPECT_EQ(RefData, toReference(FormValOpt, InvalidU64));
+  EXPECT_EQ(InvalidU64, toAddress(FormValOpt, InvalidU64));
+  EXPECT_EQ(InvalidU64, toSectionOffset(FormValOpt, InvalidU64));
+  EXPECT_EQ(InvalidS64, toSigned(FormValOpt, InvalidU64));
+
+  // Test successful and unsuccessful signed constant decoding.
+  int64_t SData8 = 0x1020304050607080ULL;
+  FormVal.setForm(DW_FORM_udata);
+  FormVal.setSValue(SData8);
+  FormValOpt = FormVal;
+  
+  EXPECT_FALSE(toString(FormValOpt).hasValue());
+  EXPECT_TRUE(toUnsigned(FormValOpt).hasValue());
+  EXPECT_FALSE(toReference(FormValOpt).hasValue());
+  EXPECT_TRUE(toSigned(FormValOpt).hasValue());
+  EXPECT_FALSE(toAddress(FormValOpt).hasValue());
+  EXPECT_FALSE(toSectionOffset(FormValOpt).hasValue());
+  EXPECT_FALSE(toBlock(FormValOpt).hasValue());
+  EXPECT_EQ(nullptr, toString(FormValOpt, nullptr));
+  EXPECT_EQ((uint64_t)SData8, toUnsigned(FormValOpt, InvalidU64));
+  EXPECT_EQ(InvalidU64, toReference(FormValOpt, InvalidU64));
+  EXPECT_EQ(InvalidU64, toAddress(FormValOpt, InvalidU64));
+  EXPECT_EQ(InvalidU64, toSectionOffset(FormValOpt, InvalidU64));
+  EXPECT_EQ(SData8, toSigned(FormValOpt, InvalidU64));
+
+  // Test successful and unsuccessful block decoding.
+  uint8_t Data[] = { 2, 3, 4 };
+  ArrayRef<uint8_t> Array(Data);
+  FormVal.setForm(DW_FORM_block1);
+  FormVal.setBlockValue(Array);
+  FormValOpt = FormVal;
+  
+  EXPECT_FALSE(toString(FormValOpt).hasValue());
+  EXPECT_FALSE(toUnsigned(FormValOpt).hasValue());
+  EXPECT_FALSE(toReference(FormValOpt).hasValue());
+  EXPECT_FALSE(toSigned(FormValOpt).hasValue());
+  EXPECT_FALSE(toAddress(FormValOpt).hasValue());
+  EXPECT_FALSE(toSectionOffset(FormValOpt).hasValue());
+  auto BlockOpt = toBlock(FormValOpt);
+  EXPECT_TRUE(BlockOpt.hasValue());
+  EXPECT_EQ(*BlockOpt, Array);
+  EXPECT_EQ(nullptr, toString(FormValOpt, nullptr));
+  EXPECT_EQ(InvalidU64, toUnsigned(FormValOpt, InvalidU64));
+  EXPECT_EQ(InvalidU64, toReference(FormValOpt, InvalidU64));
+  EXPECT_EQ(InvalidU64, toAddress(FormValOpt, InvalidU64));
+  EXPECT_EQ(InvalidU64, toSectionOffset(FormValOpt, InvalidU64));
+  EXPECT_EQ(InvalidS64, toSigned(FormValOpt, InvalidU64));
+
+  // Test
+}
+
 } // end anonymous namespace




More information about the llvm-commits mailing list