[dwarfdump] Pretty print location expressions and location lists

Summary:
Based on Fred's patch here: https://reviews.llvm.org/D6771

I can't seem to commandeer the old review, so I'm creating a new one.

With that change the locations exrpessions are pretty printed inline in the
DIE tree. The output looks like this for debug_loc entries:

    DW_AT_location [DW_FORM_data4]        (0x00000000
       0x0000000000000001 - 0x000000000000000b: DW_OP_consts +3
       0x000000000000000b - 0x0000000000000012: DW_OP_consts +7
       0x0000000000000012 - 0x000000000000001b: DW_OP_reg0 RAX, DW_OP_piece 0x4
       0x000000000000001b - 0x0000000000000024: DW_OP_breg5 RDI+0)

And like this for debug_loc.dwo entries:
    DW_AT_location [DW_FORM_sec_offset]   (0x00000000
      Addr idx 2 (w/ length 190): DW_OP_consts +0, DW_OP_stack_value
      Addr idx 3 (w/ length 23): DW_OP_reg0 RAX, DW_OP_piece 0x4)

Simple locations without ranges are printed inline:

   DW_AT_location [DW_FORM_block1]       (DW_OP_reg4 RSI, DW_OP_piece 0x4, DW_OP_bit_piece 0x20 0x0)

The debug_loc(.dwo) dumping in changed accordingly to factor the code.

Reviewers: dblaikie, aprantl, friss

Subscribers: mgorny, javed.absar, hiraditya, llvm-commits, JDevlieghere

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

llvm-svn: 312042
diff --git a/llvm/lib/DebugInfo/DWARF/CMakeLists.txt b/llvm/lib/DebugInfo/DWARF/CMakeLists.txt
index 11f9450..620016d 100644
--- a/llvm/lib/DebugInfo/DWARF/CMakeLists.txt
+++ b/llvm/lib/DebugInfo/DWARF/CMakeLists.txt
@@ -15,6 +15,7 @@
   DWARFDebugPubTable.cpp
   DWARFDebugRangeList.cpp
   DWARFDie.cpp
+  DWARFExpression.cpp
   DWARFFormValue.cpp
   DWARFGdbIndex.cpp
   DWARFTypeUnit.cpp
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp b/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp
index 0bd9c92..27d9db6 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp
@@ -31,6 +31,7 @@
 #include "llvm/DebugInfo/DWARF/DWARFSection.h"
 #include "llvm/DebugInfo/DWARF/DWARFUnitIndex.h"
 #include "llvm/DebugInfo/DWARF/DWARFVerifier.h"
+#include "llvm/MC/MCRegisterInfo.h"
 #include "llvm/Object/Decompressor.h"
 #include "llvm/Object/MachO.h"
 #include "llvm/Object/ObjectFile.h"
@@ -40,6 +41,7 @@
 #include "llvm/Support/Error.h"
 #include "llvm/Support/Format.h"
 #include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/TargetRegistry.h"
 #include "llvm/Support/raw_ostream.h"
 #include <algorithm>
 #include <cstdint>
@@ -59,6 +61,12 @@
 using FileLineInfoKind = DILineInfoSpecifier::FileLineInfoKind;
 using FunctionNameKind = DILineInfoSpecifier::FunctionNameKind;
 
+DWARFContext::DWARFContext(std::unique_ptr<const DWARFObject> DObj,
+                           std::string DWPName)
+    : DIContext(CK_DWARF), DWPName(std::move(DWPName)), DObj(std::move(DObj)) {}
+
+DWARFContext::~DWARFContext() = default;
+
 static void dumpAccelSection(raw_ostream &OS, StringRef Name,
                              const DWARFObject &Obj,
                              const DWARFSection &Section,
@@ -237,12 +245,12 @@
 
   if (DumpType == DIDT_All || DumpType == DIDT_Loc) {
     OS << "\n.debug_loc contents:\n";
-    getDebugLoc()->dump(OS);
+    getDebugLoc()->dump(OS, getRegisterInfo());
   }
 
   if (DumpType == DIDT_All || DumpType == DIDT_LocDwo) {
     OS << "\n.debug_loc.dwo contents:\n";
-    getDebugLocDWO()->dump(OS);
+    getDebugLocDWO()->dump(OS, getRegisterInfo());
   }
 
   if (DumpType == DIDT_All || DumpType == DIDT_Frames) {
@@ -1295,3 +1303,19 @@
       llvm::make_unique<DWARFObjInMemory>(Sections, AddrSize, isLittleEndian);
   return llvm::make_unique<DWARFContext>(std::move(DObj), "");
 }
+
+Error DWARFContext::loadRegisterInfo(const object::ObjectFile &Obj) {
+  // Detect the architecture from the object file. We usually don't need OS
+  // info to lookup a target and create register info.
+  Triple TT;
+  TT.setArch(Triple::ArchType(Obj.getArch()));
+  TT.setVendor(Triple::UnknownVendor);
+  TT.setOS(Triple::UnknownOS);
+  std::string TargetLookupError;
+  const Target *TheTarget =
+      TargetRegistry::lookupTarget(TT.str(), TargetLookupError);
+  if (!TargetLookupError.empty())
+    return make_error<StringError>(TargetLookupError, inconvertibleErrorCode());
+  RegInfo.reset(TheTarget->createMCRegInfo(TT.str()));
+  return Error::success();
+}
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp
index c240dd7..68bc0e5 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp
@@ -11,7 +11,10 @@
 #include "llvm/ADT/StringRef.h"
 #include "llvm/BinaryFormat/Dwarf.h"
 #include "llvm/DebugInfo/DWARF/DWARFContext.h"
+#include "llvm/DebugInfo/DWARF/DWARFExpression.h"
 #include "llvm/DebugInfo/DWARF/DWARFRelocMap.h"
+#include "llvm/DebugInfo/DWARF/DWARFUnit.h"
+#include "llvm/Support/Compiler.h"
 #include "llvm/Support/Format.h"
 #include "llvm/Support/raw_ostream.h"
 #include <algorithm>
@@ -20,104 +23,160 @@
 
 using namespace llvm;
 
-void DWARFDebugLoc::dump(raw_ostream &OS) const {
+// When directly dumping the .debug_loc without a compile unit, we have to guess
+// at the DWARF version. This only affects DW_OP_call_ref, which is a rare
+// expression that LLVM doesn't produce. Guessing the wrong version means we
+// won't be able to pretty print expressions in DWARF2 binaries produced by
+// non-LLVM tools.
+static void dumpExpression(raw_ostream &OS, ArrayRef<char> Data,
+                           bool IsLittleEndian, unsigned AddressSize,
+                           const MCRegisterInfo *MRI) {
+  DWARFDataExtractor Extractor(StringRef(Data.data(), Data.size()),
+                               IsLittleEndian, AddressSize);
+  DWARFExpression(Extractor, AddressSize, dwarf::DWARF_VERSION).print(OS, MRI);
+}
+
+void DWARFDebugLoc::LocationList::dump(raw_ostream &OS, bool IsLittleEndian,
+                                       unsigned AddressSize,
+                                       const MCRegisterInfo *MRI,
+                                       unsigned Indent) const {
+  for (const Entry &E : Entries) {
+    OS << '\n';
+    OS.indent(Indent);
+    OS << format("0x%016" PRIx64, E.Begin) << " - "
+       << format("0x%016" PRIx64, E.End) << ": ";
+
+    dumpExpression(OS, E.Loc, IsLittleEndian, AddressSize, MRI);
+  }
+}
+
+void DWARFDebugLoc::dump(raw_ostream &OS, const MCRegisterInfo *MRI) const {
   for (const LocationList &L : Locations) {
     OS << format("0x%8.8x: ", L.Offset);
-    const unsigned Indent = 12;
-    for (const Entry &E : L.Entries) {
-      if (&E != L.Entries.begin())
-        OS.indent(Indent);
-      OS << "Beginning address offset: " << format("0x%016" PRIx64, E.Begin)
-         << '\n';
-      OS.indent(Indent) << "   Ending address offset: "
-                        << format("0x%016" PRIx64, E.End) << '\n';
-      OS.indent(Indent) << "    Location description: ";
-      for (unsigned char Loc : E.Loc) {
-        OS << format("%2.2x ", Loc);
-      }
-      OS << "\n\n";
+    L.dump(OS, IsLittleEndian, AddressSize, MRI, 12);
+    OS << "\n\n";
+  }
+}
+
+Optional<DWARFDebugLoc::LocationList>
+DWARFDebugLoc::parseOneLocationList(DWARFDataExtractor Data, unsigned *Offset) {
+  LocationList LL;
+  LL.Offset = *Offset;
+
+  // 2.6.2 Location Lists
+  // A location list entry consists of:
+  while (true) {
+    Entry E;
+    if (!Data.isValidOffsetForDataOfSize(*Offset, 2 * Data.getAddressSize())) {
+      llvm::errs() << "Location list overflows the debug_loc section.\n";
+      return None;
     }
+
+    // 1. A beginning address offset. ...
+    E.Begin = Data.getRelocatedAddress(Offset);
+
+    // 2. An ending address offset. ...
+    E.End = Data.getRelocatedAddress(Offset);
+
+    // The end of any given location list is marked by an end of list entry,
+    // which consists of a 0 for the beginning address offset and a 0 for the
+    // ending address offset.
+    if (E.Begin == 0 && E.End == 0)
+      return LL;
+
+    if (!Data.isValidOffsetForDataOfSize(*Offset, 2)) {
+      llvm::errs() << "Location list overflows the debug_loc section.\n";
+      return None;
+    }
+
+    unsigned Bytes = Data.getU16(Offset);
+    if (!Data.isValidOffsetForDataOfSize(*Offset, Bytes)) {
+      llvm::errs() << "Location list overflows the debug_loc section.\n";
+      return None;
+    }
+    // A single location description describing the location of the object...
+    StringRef str = Data.getData().substr(*Offset, Bytes);
+    *Offset += Bytes;
+    E.Loc.reserve(str.size());
+    std::copy(str.begin(), str.end(), std::back_inserter(E.Loc));
+    LL.Entries.push_back(std::move(E));
   }
 }
 
 void DWARFDebugLoc::parse(const DWARFDataExtractor &data) {
+  IsLittleEndian = data.isLittleEndian();
+  AddressSize = data.getAddressSize();
+
   uint32_t Offset = 0;
-  while (data.isValidOffset(Offset+data.getAddressSize()-1)) {
-    Locations.resize(Locations.size() + 1);
-    LocationList &Loc = Locations.back();
-    Loc.Offset = Offset;
-    // 2.6.2 Location Lists
-    // A location list entry consists of:
-    while (true) {
-      // A beginning and ending address offsets.
-      Entry E;
-      E.Begin = data.getRelocatedAddress(&Offset);
-      E.End = data.getRelocatedAddress(&Offset);
-
-      // The end of any given location list is marked by an end of list entry,
-      // which consists of a 0 for the beginning address offset and a 0 for the
-      // ending address offset.
-      if (E.Begin == 0 && E.End == 0)
-        break;
-
-      unsigned Bytes = data.getU16(&Offset);
-      // A single location description describing the location of the object...
-      StringRef str = data.getData().substr(Offset, Bytes);
-      Offset += Bytes;
-      E.Loc.append(str.begin(), str.end());
-      Loc.Entries.push_back(std::move(E));
-    }
+  while (data.isValidOffset(Offset + data.getAddressSize() - 1)) {
+    if (auto LL = parseOneLocationList(data, &Offset))
+      Locations.push_back(std::move(*LL));
+    else
+      break;
   }
   if (data.isValidOffset(Offset))
     errs() << "error: failed to consume entire .debug_loc section\n";
 }
 
+Optional<DWARFDebugLocDWO::LocationList>
+DWARFDebugLocDWO::parseOneLocationList(DataExtractor Data, unsigned *Offset) {
+  LocationList LL;
+  LL.Offset = *Offset;
+
+  // dwarf::DW_LLE_end_of_list_entry is 0 and indicates the end of the list.
+  while (auto Kind =
+             static_cast<dwarf::LocationListEntry>(Data.getU8(Offset))) {
+    if (Kind != dwarf::DW_LLE_startx_length) {
+      llvm::errs() << "error: dumping support for LLE of kind " << (int)Kind
+                   << " not implemented\n";
+      return None;
+    }
+
+    Entry E;
+    E.Start = Data.getULEB128(Offset);
+    E.Length = Data.getU32(Offset);
+
+    unsigned Bytes = Data.getU16(Offset);
+    // A single location description describing the location of the object...
+    StringRef str = Data.getData().substr(*Offset, Bytes);
+    *Offset += Bytes;
+    E.Loc.resize(str.size());
+    std::copy(str.begin(), str.end(), E.Loc.begin());
+
+    LL.Entries.push_back(std::move(E));
+  }
+  return LL;
+}
+
 void DWARFDebugLocDWO::parse(DataExtractor data) {
+  IsLittleEndian = data.isLittleEndian();
+  AddressSize = data.getAddressSize();
+
   uint32_t Offset = 0;
   while (data.isValidOffset(Offset)) {
-    Locations.resize(Locations.size() + 1);
-    LocationList &Loc = Locations.back();
-    Loc.Offset = Offset;
-    dwarf::LocationListEntry Kind;
-    while ((Kind = static_cast<dwarf::LocationListEntry>(
-                data.getU8(&Offset))) != dwarf::DW_LLE_end_of_list) {
-
-      if (Kind != dwarf::DW_LLE_startx_length) {
-        errs() << "error: dumping support for LLE of kind " << (int)Kind
-               << " not implemented\n";
-        return;
-      }
-
-      Entry E;
-
-      E.Start = data.getULEB128(&Offset);
-      E.Length = data.getU32(&Offset);
-
-      unsigned Bytes = data.getU16(&Offset);
-      // A single location description describing the location of the object...
-      StringRef str = data.getData().substr(Offset, Bytes);
-      Offset += Bytes;
-      E.Loc.resize(str.size());
-      std::copy(str.begin(), str.end(), E.Loc.begin());
-
-      Loc.Entries.push_back(std::move(E));
-    }
+    if (auto LL = parseOneLocationList(data, &Offset))
+      Locations.push_back(std::move(*LL));
+    else
+      return;
   }
 }
 
-void DWARFDebugLocDWO::dump(raw_ostream &OS) const {
+void DWARFDebugLocDWO::LocationList::dump(raw_ostream &OS, bool IsLittleEndian,
+                                          unsigned AddressSize,
+                                          const MCRegisterInfo *MRI,
+                                          unsigned Indent) const {
+  for (const Entry &E : Entries) {
+    OS << '\n';
+    OS.indent(Indent);
+    OS << "Addr idx " << E.Start << " (w/ length " << E.Length << "): ";
+    dumpExpression(OS, E.Loc, IsLittleEndian, AddressSize, MRI);
+  }
+}
+
+void DWARFDebugLocDWO::dump(raw_ostream &OS, const MCRegisterInfo *MRI) const {
   for (const LocationList &L : Locations) {
     OS << format("0x%8.8x: ", L.Offset);
-    const unsigned Indent = 12;
-    for (const Entry &E : L.Entries) {
-      if (&E != L.Entries.begin())
-        OS.indent(Indent);
-      OS << "Beginning address index: " << E.Start << '\n';
-      OS.indent(Indent) << "                 Length: " << E.Length << '\n';
-      OS.indent(Indent) << "   Location description: ";
-      for (unsigned char Loc : E.Loc)
-        OS << format("%2.2x ", Loc);
-      OS << "\n\n";
-    }
+    L.dump(OS, IsLittleEndian, AddressSize, MRI, /*Indent=*/12);
+    OS << "\n\n";
   }
 }
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp
index 9ad4b52..261a5ca 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp
@@ -16,6 +16,7 @@
 #include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h"
 #include "llvm/DebugInfo/DWARF/DWARFContext.h"
 #include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h"
+#include "llvm/DebugInfo/DWARF/DWARFExpression.h"
 #include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
 #include "llvm/DebugInfo/DWARF/DWARFUnit.h"
 #include "llvm/Object/ObjectFile.h"
@@ -81,6 +82,47 @@
   }
 }
 
+static void dumpLocation(raw_ostream &OS, DWARFFormValue &FormValue,
+                         DWARFUnit *U, unsigned Indent) {
+  DWARFContext &Ctx = U->getContext();
+  const DWARFObject &Obj = Ctx.getDWARFObj();
+  const MCRegisterInfo *MRI = Ctx.getRegisterInfo();
+  if (FormValue.isFormClass(DWARFFormValue::FC_Block) ||
+      FormValue.isFormClass(DWARFFormValue::FC_Exprloc)) {
+    ArrayRef<uint8_t> Expr = *FormValue.getAsBlock();
+    DataExtractor Data(StringRef((const char *)Expr.data(), Expr.size()),
+                       Ctx.isLittleEndian(), 0);
+    DWARFExpression(Data, U->getVersion(), U->getAddressByteSize())
+        .print(OS, MRI);
+    return;
+  }
+
+  FormValue.dump(OS);
+  if (FormValue.isFormClass(DWARFFormValue::FC_SectionOffset)) {
+    const DWARFSection &LocSection = Obj.getLocSection();
+    const DWARFSection &LocDWOSection = Obj.getLocDWOSection();
+    uint32_t Offset = *FormValue.getAsSectionOffset();
+
+    if (!LocSection.Data.empty()) {
+      DWARFDebugLoc DebugLoc;
+      DWARFDataExtractor Data(Obj, LocSection, Ctx.isLittleEndian(),
+                              Obj.getAddressSize());
+      auto LL = DebugLoc.parseOneLocationList(Data, &Offset);
+      if (LL)
+        LL->dump(OS, Ctx.isLittleEndian(), Obj.getAddressSize(), MRI, Indent);
+      else
+        OS << "error extracting location list.";
+    } else if (!LocDWOSection.Data.empty()) {
+      DataExtractor Data(LocDWOSection.Data, Ctx.isLittleEndian(), 0);
+      auto LL = DWARFDebugLocDWO::parseOneLocationList(Data, &Offset);
+      if (LL)
+        LL->dump(OS, Ctx.isLittleEndian(), Obj.getAddressSize(), MRI, Indent);
+      else
+        OS << "error extracting location list.";
+    }
+  }
+}
+
 static void dumpAttribute(raw_ostream &OS, const DWARFDie &Die,
                           uint32_t *OffsetPtr, dwarf::Attribute Attr,
                           dwarf::Form Form, unsigned Indent,
@@ -129,6 +171,9 @@
     WithColor(OS, Color) << Name;
   else if (Attr == DW_AT_decl_line || Attr == DW_AT_call_line)
     OS << *formValue.getAsUnsignedConstant();
+  else if (Attr == DW_AT_location || Attr == DW_AT_frame_base ||
+           Attr == DW_AT_data_member_location)
+    dumpLocation(OS, formValue, U, sizeof(BaseIndent) + Indent + 4);
   else
     formValue.dump(OS, DumpOpts);
 
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFExpression.cpp b/llvm/lib/DebugInfo/DWARF/DWARFExpression.cpp
new file mode 100644
index 0000000..3417fee
--- /dev/null
+++ b/llvm/lib/DebugInfo/DWARF/DWARFExpression.cpp
@@ -0,0 +1,272 @@
+//===-- DWARFExpression.cpp -----------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/DWARF/DWARFExpression.h"
+#include "llvm/BinaryFormat/Dwarf.h"
+#include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h"
+#include "llvm/DebugInfo/DWARF/DWARFContext.h"
+#include "llvm/MC/MCRegisterInfo.h"
+#include "llvm/Support/Format.h"
+#include <cassert>
+#include <cstdint>
+#include <vector>
+
+using namespace llvm;
+using namespace dwarf;
+
+namespace llvm {
+
+typedef std::vector<DWARFExpression::Operation::Description> DescVector;
+
+static DescVector getDescriptions() {
+  DescVector Descriptions;
+  typedef DWARFExpression::Operation Op;
+  typedef Op::Description Desc;
+
+  Descriptions.resize(0xff);
+  Descriptions[DW_OP_addr] = Desc(Op::Dwarf2, Op::SizeAddr);
+  Descriptions[DW_OP_deref] = Desc(Op::Dwarf2);
+  Descriptions[DW_OP_const1u] = Desc(Op::Dwarf2, Op::Size1);
+  Descriptions[DW_OP_const1s] = Desc(Op::Dwarf2, Op::SignedSize1);
+  Descriptions[DW_OP_const2u] = Desc(Op::Dwarf2, Op::Size2);
+  Descriptions[DW_OP_const2s] = Desc(Op::Dwarf2, Op::SignedSize2);
+  Descriptions[DW_OP_const4u] = Desc(Op::Dwarf2, Op::Size4);
+  Descriptions[DW_OP_const4s] = Desc(Op::Dwarf2, Op::SignedSize4);
+  Descriptions[DW_OP_const8u] = Desc(Op::Dwarf2, Op::Size8);
+  Descriptions[DW_OP_const8s] = Desc(Op::Dwarf2, Op::SignedSize8);
+  Descriptions[DW_OP_constu] = Desc(Op::Dwarf2, Op::SizeLEB);
+  Descriptions[DW_OP_consts] = Desc(Op::Dwarf2, Op::SignedSizeLEB);
+  Descriptions[DW_OP_dup] = Desc(Op::Dwarf2);
+  Descriptions[DW_OP_drop] = Desc(Op::Dwarf2);
+  Descriptions[DW_OP_over] = Desc(Op::Dwarf2);
+  Descriptions[DW_OP_pick] = Desc(Op::Dwarf2, Op::Size1);
+  Descriptions[DW_OP_swap] = Desc(Op::Dwarf2);
+  Descriptions[DW_OP_rot] = Desc(Op::Dwarf2);
+  Descriptions[DW_OP_xderef] = Desc(Op::Dwarf2);
+  Descriptions[DW_OP_abs] = Desc(Op::Dwarf2);
+  Descriptions[DW_OP_and] = Desc(Op::Dwarf2);
+  Descriptions[DW_OP_div] = Desc(Op::Dwarf2);
+  Descriptions[DW_OP_minus] = Desc(Op::Dwarf2);
+  Descriptions[DW_OP_mod] = Desc(Op::Dwarf2);
+  Descriptions[DW_OP_mul] = Desc(Op::Dwarf2);
+  Descriptions[DW_OP_neg] = Desc(Op::Dwarf2);
+  Descriptions[DW_OP_not] = Desc(Op::Dwarf2);
+  Descriptions[DW_OP_or] = Desc(Op::Dwarf2);
+  Descriptions[DW_OP_plus] = Desc(Op::Dwarf2);
+  Descriptions[DW_OP_plus_uconst] = Desc(Op::Dwarf2, Op::SizeLEB);
+  Descriptions[DW_OP_shl] = Desc(Op::Dwarf2);
+  Descriptions[DW_OP_shr] = Desc(Op::Dwarf2);
+  Descriptions[DW_OP_shra] = Desc(Op::Dwarf2);
+  Descriptions[DW_OP_xor] = Desc(Op::Dwarf2);
+  Descriptions[DW_OP_skip] = Desc(Op::Dwarf2, Op::SignedSize2);
+  Descriptions[DW_OP_bra] = Desc(Op::Dwarf2, Op::SignedSize2);
+  Descriptions[DW_OP_eq] = Desc(Op::Dwarf2);
+  Descriptions[DW_OP_ge] = Desc(Op::Dwarf2);
+  Descriptions[DW_OP_gt] = Desc(Op::Dwarf2);
+  Descriptions[DW_OP_le] = Desc(Op::Dwarf2);
+  Descriptions[DW_OP_lt] = Desc(Op::Dwarf2);
+  Descriptions[DW_OP_ne] = Desc(Op::Dwarf2);
+  for (uint16_t LA = DW_OP_lit0; LA <= DW_OP_lit31; ++LA)
+    Descriptions[LA] = Desc(Op::Dwarf2);
+  for (uint16_t LA = DW_OP_reg0; LA <= DW_OP_reg31; ++LA)
+    Descriptions[LA] = Desc(Op::Dwarf2);
+  for (uint16_t LA = DW_OP_breg0; LA <= DW_OP_breg31; ++LA)
+    Descriptions[LA] = Desc(Op::Dwarf2, Op::SignedSizeLEB);
+  Descriptions[DW_OP_regx] = Desc(Op::Dwarf2, Op::SizeLEB);
+  Descriptions[DW_OP_fbreg] = Desc(Op::Dwarf2, Op::SignedSizeLEB);
+  Descriptions[DW_OP_bregx] = Desc(Op::Dwarf2, Op::SizeLEB, Op::SignedSizeLEB);
+  Descriptions[DW_OP_piece] = Desc(Op::Dwarf2, Op::SizeLEB);
+  Descriptions[DW_OP_deref_size] = Desc(Op::Dwarf2, Op::Size1);
+  Descriptions[DW_OP_xderef_size] = Desc(Op::Dwarf2, Op::Size1);
+  Descriptions[DW_OP_nop] = Desc(Op::Dwarf2);
+  Descriptions[DW_OP_push_object_address] = Desc(Op::Dwarf3);
+  Descriptions[DW_OP_call2] = Desc(Op::Dwarf3, Op::Size2);
+  Descriptions[DW_OP_call4] = Desc(Op::Dwarf3, Op::Size4);
+  Descriptions[DW_OP_call_ref] = Desc(Op::Dwarf3, Op::SizeRefAddr);
+  Descriptions[DW_OP_form_tls_address] = Desc(Op::Dwarf3);
+  Descriptions[DW_OP_call_frame_cfa] = Desc(Op::Dwarf3);
+  Descriptions[DW_OP_bit_piece] = Desc(Op::Dwarf3, Op::SizeLEB, Op::SizeLEB);
+  Descriptions[DW_OP_implicit_value] =
+      Desc(Op::Dwarf3, Op::SizeLEB, Op::SizeBlock);
+  Descriptions[DW_OP_stack_value] = Desc(Op::Dwarf3);
+  Descriptions[DW_OP_GNU_push_tls_address] = Desc(Op::Dwarf3);
+  Descriptions[DW_OP_GNU_addr_index] = Desc(Op::Dwarf4, Op::SizeLEB);
+  Descriptions[DW_OP_GNU_const_index] = Desc(Op::Dwarf4, Op::SizeLEB);
+  return Descriptions;
+}
+
+static DWARFExpression::Operation::Description getOpDesc(unsigned OpCode) {
+  // FIXME: Make this constexpr once all compilers are smart enough to do it.
+  static DescVector Descriptions = getDescriptions();
+  assert(OpCode < Descriptions.size());
+  return Descriptions[OpCode];
+}
+
+static uint8_t getRefAddrSize(uint8_t AddrSize, uint16_t Version) {
+  return (Version == 2) ? AddrSize : 4;
+}
+
+bool DWARFExpression::Operation::extract(DataExtractor Data, uint16_t Version,
+                                         uint8_t AddressSize, uint32_t Offset) {
+  Opcode = Data.getU8(&Offset);
+
+  Desc = getOpDesc(Opcode);
+  if (Desc.Version == Operation::DwarfNA)
+    return false;
+
+  for (unsigned Operand = 0; Operand < 2; ++Operand) {
+    unsigned Size = Desc.Op[Operand];
+    unsigned Signed = Size & Operation::SignBit;
+
+    if (Size == Operation::SizeNA)
+      break;
+
+    switch (Size & ~Operation::SignBit) {
+    case Operation::Size1:
+      Operands[Operand] = Data.getU8(&Offset);
+      if (Signed)
+        Operands[Operand] = (int8_t)Operands[Operand];
+      break;
+    case Operation::Size2:
+      Operands[Operand] = Data.getU16(&Offset);
+      if (Signed)
+        Operands[Operand] = (int16_t)Operands[Operand];
+      break;
+    case Operation::Size4:
+      Operands[Operand] = Data.getU32(&Offset);
+      if (Signed)
+        Operands[Operand] = (int32_t)Operands[Operand];
+      break;
+    case Operation::Size8:
+      Operands[Operand] = Data.getU64(&Offset);
+      break;
+    case Operation::SizeAddr:
+      if (AddressSize == 8) {
+        Operands[Operand] = Data.getU64(&Offset);
+      } else {
+        assert(AddressSize == 4);
+        Operands[Operand] = Data.getU32(&Offset);
+      }
+      break;
+    case Operation::SizeRefAddr:
+      if (getRefAddrSize(AddressSize, Version) == 8) {
+        Operands[Operand] = Data.getU64(&Offset);
+      } else {
+        assert(getRefAddrSize(AddressSize, Version) == 4);
+        Operands[Operand] = Data.getU32(&Offset);
+      }
+      break;
+    case Operation::SizeLEB:
+      if (Signed)
+        Operands[Operand] = Data.getSLEB128(&Offset);
+      else
+        Operands[Operand] = Data.getULEB128(&Offset);
+      break;
+    case Operation::SizeBlock:
+      // We need a size, so this cannot be the first operand
+      if (Operand == 0)
+        return false;
+      // Store the offset of the block as the value.
+      Operands[Operand] = Offset;
+      Offset += Operands[Operand - 1];
+      break;
+    default:
+      llvm_unreachable("Unknown DWARFExpression Op size");
+    }
+  }
+
+  EndOffset = Offset;
+  return true;
+}
+
+static bool prettyPrintRegisterOp(raw_ostream &OS, uint8_t Opcode,
+                                  uint64_t Operands[2],
+                                  const MCRegisterInfo *MRI, bool isEH) {
+  if (!MRI)
+    return false;
+
+  uint64_t DwarfRegNum;
+  unsigned OpNum = 0;
+
+  if (Opcode == DW_OP_bregx || Opcode == DW_OP_regx)
+    DwarfRegNum = Operands[OpNum++];
+  else if (Opcode >= DW_OP_breg0 && Opcode < DW_OP_bregx)
+    DwarfRegNum = Opcode - DW_OP_breg0;
+  else
+    DwarfRegNum = Opcode - DW_OP_reg0;
+
+  int LLVMRegNum = MRI->getLLVMRegNum(DwarfRegNum, isEH);
+  if (LLVMRegNum >= 0) {
+    if (const char *RegName = MRI->getName(LLVMRegNum)) {
+      if ((Opcode >= DW_OP_breg0 && Opcode <= DW_OP_breg31) ||
+          Opcode == DW_OP_bregx)
+        OS << format(" %s%+" PRId64, RegName, Operands[OpNum]);
+      else
+        OS << ' ' << RegName;
+      return true;
+    }
+  }
+
+  return false;
+}
+
+bool DWARFExpression::Operation::print(raw_ostream &OS,
+                                       const DWARFExpression *Expr,
+                                       const MCRegisterInfo *RegInfo,
+                                       bool isEH) {
+  if (Error) {
+    OS << "decoding error.";
+    return false;
+  }
+
+  StringRef Name = OperationEncodingString(Opcode);
+  assert(!Name.empty() && "DW_OP has no name!");
+  OS << Name;
+
+  if ((Opcode >= DW_OP_breg0 && Opcode <= DW_OP_breg31) ||
+      (Opcode >= DW_OP_reg0 && Opcode <= DW_OP_reg31) ||
+      Opcode == DW_OP_bregx || Opcode == DW_OP_regx)
+    if (prettyPrintRegisterOp(OS, Opcode, Operands, RegInfo, isEH))
+      return true;
+
+  for (unsigned Operand = 0; Operand < 2; ++Operand) {
+    unsigned Size = Desc.Op[Operand];
+    unsigned Signed = Size & Operation::SignBit;
+
+    if (Size == Operation::SizeNA)
+      break;
+
+    if (Size == Operation::SizeBlock) {
+      uint32_t Offset = Operands[Operand];
+      for (unsigned i = 0; i < Operands[Operand - 1]; ++i)
+        OS << format(" 0x%02x", Expr->Data.getU8(&Offset));
+    } else {
+      if (Signed)
+        OS << format(" %+" PRId64, (int64_t)Operands[Operand]);
+      else
+        OS << format(" 0x%" PRIx64, Operands[Operand]);
+    }
+  }
+  return true;
+}
+
+void DWARFExpression::print(raw_ostream &OS, const MCRegisterInfo *RegInfo) {
+  for (auto &Op : *this) {
+    if (!Op.print(OS, this, RegInfo, /* isEH */ false)) {
+      uint32_t FailOffset = Op.getEndOffset();
+      while (FailOffset < Data.getData().size())
+        OS << format(" %02x", Data.getU8(&FailOffset));
+      return;
+    }
+    if (Op.getEndOffset() < Data.getData().size())
+      OS << ", ";
+  }
+}
+
+} // namespace llvm
diff --git a/llvm/lib/DebugInfo/DWARF/LLVMBuild.txt b/llvm/lib/DebugInfo/DWARF/LLVMBuild.txt
index 8242a7f..a212762 100644
--- a/llvm/lib/DebugInfo/DWARF/LLVMBuild.txt
+++ b/llvm/lib/DebugInfo/DWARF/LLVMBuild.txt
@@ -19,4 +19,4 @@
 type = Library
 name = DebugInfoDWARF
 parent = DebugInfo
-required_libraries = BinaryFormat Object Support
+required_libraries = BinaryFormat Object MC Support