https://github.com/Sterling-Augustine created 
https://github.com/llvm/llvm-project/pull/145959

…145081)"

This reverts commit cbf781f0bdf2f680abbe784faedeefd6f84c246e.

Breaks a couple of buildbots.

>From 47fa4a6385cb4e8964cc6909c3554f6589b66eef Mon Sep 17 00:00:00 2001
From: Sterling Augustine <saugust...@google.com>
Date: Thu, 26 Jun 2025 12:03:33 -0700
Subject: [PATCH] Revert "[NFC][DebugInfo][DWARF] Create new low-level dwarf
 library (#145081)"

This reverts commit cbf781f0bdf2f680abbe784faedeefd6f84c246e.

Breaks a couple of buildbots.
---
 bolt/include/bolt/Core/DIEBuilder.h           |   2 +-
 bolt/lib/Core/CMakeLists.txt                  |   1 -
 bolt/lib/Core/DIEBuilder.cpp                  |   2 +-
 bolt/lib/Core/DebugNames.cpp                  |   2 +-
 bolt/lib/Rewrite/CMakeLists.txt               |   1 -
 bolt/lib/Rewrite/DWARFRewriter.cpp            |   2 +-
 lldb/source/Expression/DWARFExpression.cpp    |   5 +-
 lldb/source/Symbol/UnwindPlan.cpp             |   6 +-
 .../Symbol/PostfixExpressionTest.cpp          |   5 +-
 .../PdbFPOProgramToDWARFExpressionTests.cpp   |   5 +-
 llvm/include/llvm/DWARFLinker/AddressesMap.h  |   2 +-
 .../llvm/DWARFLinker/Classic/DWARFLinker.h    |   2 +-
 .../llvm/DWARFLinker/DWARFLinkerBase.h        |   2 +-
 .../llvm/DebugInfo/DWARF/DWARFCFIPrinter.h    |   2 +-
 .../DWARF/{LowLevel => }/DWARFCFIProgram.h    | 150 +----
 .../llvm/DebugInfo/DWARF/DWARFDataExtractor.h |   2 +-
 .../{LowLevel => }/DWARFDataExtractorSimple.h |   0
 .../llvm/DebugInfo/DWARF/DWARFDebugFrame.h    |   4 +-
 .../DWARF/{LowLevel => }/DWARFExpression.h    |  63 +-
 .../DebugInfo/DWARF/DWARFExpressionPrinter.h  |  66 ---
 .../llvm/DebugInfo/DWARF/DWARFVerifier.h      |   2 +-
 llvm/lib/CodeGen/AsmPrinter/CMakeLists.txt    |   1 -
 llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp    |   2 +-
 llvm/lib/DWARFLinker/Classic/CMakeLists.txt   |   1 -
 llvm/lib/DWARFLinker/Classic/DWARFLinker.cpp  |   2 +-
 .../Classic/DWARFLinkerCompileUnit.cpp        |   2 +-
 llvm/lib/DebugInfo/DWARF/CMakeLists.txt       |   6 +-
 llvm/lib/DebugInfo/DWARF/DWARFCFIPrinter.cpp  |   6 +-
 .../DWARF/{LowLevel => }/DWARFCFIProgram.cpp  | 148 ++++-
 llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp  |   7 +-
 llvm/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp    |   5 +-
 llvm/lib/DebugInfo/DWARF/DWARFDie.cpp         |   5 +-
 llvm/lib/DebugInfo/DWARF/DWARFExpression.cpp  | 538 ++++++++++++++++++
 .../DWARF/DWARFExpressionPrinter.cpp          | 311 ----------
 llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp        |   2 +-
 llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp    |   2 +-
 .../DebugInfo/DWARF/LowLevel/CMakeLists.txt   |  14 -
 .../DWARF/LowLevel/DWARFExpression.cpp        | 253 --------
 .../LogicalView/Readers/LVDWARFReader.cpp     |   6 +-
 llvm/lib/ProfileData/CMakeLists.txt           |   1 -
 llvm/lib/ProfileData/InstrProfCorrelator.cpp  |   2 +-
 llvm/tools/dsymutil/CMakeLists.txt            |   1 -
 llvm/tools/dsymutil/DwarfLinkerForBinary.cpp  |   2 +-
 llvm/tools/llvm-dwarfdump/CMakeLists.txt      |   1 -
 llvm/tools/llvm-dwarfdump/Statistics.cpp      |   2 +-
 llvm/tools/llvm-dwarfutil/CMakeLists.txt      |   1 -
 llvm/tools/llvm-dwarfutil/DebugInfoLinker.cpp |   2 +-
 llvm/tools/llvm-objdump/CMakeLists.txt        |   1 -
 llvm/tools/llvm-objdump/SourcePrinter.cpp     |   5 +-
 llvm/unittests/DebugInfo/DWARF/CMakeLists.txt |   1 -
 .../DWARFExpressionCompactPrinterTest.cpp     |   5 +-
 .../DWARF/DWARFExpressionCopyBytesTest.cpp    |   2 +-
 .../llvm-project-overlay/bolt/BUILD.bazel     |   2 -
 .../llvm-project-overlay/llvm/BUILD.bazel     |  24 -
 54 files changed, 800 insertions(+), 889 deletions(-)
 rename llvm/include/llvm/DebugInfo/DWARF/{LowLevel => }/DWARFCFIProgram.h (50%)
 rename llvm/include/llvm/DebugInfo/DWARF/{LowLevel => 
}/DWARFDataExtractorSimple.h (100%)
 rename llvm/include/llvm/DebugInfo/DWARF/{LowLevel => }/DWARFExpression.h (67%)
 delete mode 100644 llvm/include/llvm/DebugInfo/DWARF/DWARFExpressionPrinter.h
 rename llvm/lib/DebugInfo/DWARF/{LowLevel => }/DWARFCFIProgram.cpp (60%)
 create mode 100644 llvm/lib/DebugInfo/DWARF/DWARFExpression.cpp
 delete mode 100644 llvm/lib/DebugInfo/DWARF/DWARFExpressionPrinter.cpp
 delete mode 100644 llvm/lib/DebugInfo/DWARF/LowLevel/CMakeLists.txt
 delete mode 100644 llvm/lib/DebugInfo/DWARF/LowLevel/DWARFExpression.cpp

diff --git a/bolt/include/bolt/Core/DIEBuilder.h 
b/bolt/include/bolt/Core/DIEBuilder.h
index e4a4fc6b2f258..32e455ad3030a 100644
--- a/bolt/include/bolt/Core/DIEBuilder.h
+++ b/bolt/include/bolt/Core/DIEBuilder.h
@@ -20,8 +20,8 @@
 #include "llvm/CodeGen/DIE.h"
 #include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h"
 #include "llvm/DebugInfo/DWARF/DWARFDie.h"
+#include "llvm/DebugInfo/DWARF/DWARFExpression.h"
 #include "llvm/DebugInfo/DWARF/DWARFUnit.h"
-#include "llvm/DebugInfo/DWARF/LowLevel/DWARFExpression.h"
 #include "llvm/Support/Allocator.h"
 
 #include <list>
diff --git a/bolt/lib/Core/CMakeLists.txt b/bolt/lib/Core/CMakeLists.txt
index fc72dc023c590..8c1f5d0bb37b5 100644
--- a/bolt/lib/Core/CMakeLists.txt
+++ b/bolt/lib/Core/CMakeLists.txt
@@ -1,6 +1,5 @@
 set(LLVM_LINK_COMPONENTS
   DebugInfoDWARF
-  DebugInfoDWARFLowLevel
   Demangle
   MC
   MCDisassembler
diff --git a/bolt/lib/Core/DIEBuilder.cpp b/bolt/lib/Core/DIEBuilder.cpp
index b041dc5ea1cce..d36dbb3459249 100644
--- a/bolt/lib/Core/DIEBuilder.cpp
+++ b/bolt/lib/Core/DIEBuilder.cpp
@@ -14,11 +14,11 @@
 #include "llvm/CodeGen/DIE.h"
 #include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h"
 #include "llvm/DebugInfo/DWARF/DWARFDie.h"
+#include "llvm/DebugInfo/DWARF/DWARFExpression.h"
 #include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
 #include "llvm/DebugInfo/DWARF/DWARFTypeUnit.h"
 #include "llvm/DebugInfo/DWARF/DWARFUnit.h"
 #include "llvm/DebugInfo/DWARF/DWARFUnitIndex.h"
-#include "llvm/DebugInfo/DWARF/LowLevel/DWARFExpression.h"
 #include "llvm/Support/Casting.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/ErrorHandling.h"
diff --git a/bolt/lib/Core/DebugNames.cpp b/bolt/lib/Core/DebugNames.cpp
index a9d98a6ba879b..aa1c8f3d42d4b 100644
--- a/bolt/lib/Core/DebugNames.cpp
+++ b/bolt/lib/Core/DebugNames.cpp
@@ -8,8 +8,8 @@
 
 #include "bolt/Core/DebugNames.h"
 #include "bolt/Core/BinaryContext.h"
+#include "llvm/DebugInfo/DWARF/DWARFExpression.h"
 #include "llvm/DebugInfo/DWARF/DWARFTypeUnit.h"
-#include "llvm/DebugInfo/DWARF/LowLevel/DWARFExpression.h"
 #include "llvm/Support/EndianStream.h"
 #include "llvm/Support/LEB128.h"
 #include <cstdint>
diff --git a/bolt/lib/Rewrite/CMakeLists.txt b/bolt/lib/Rewrite/CMakeLists.txt
index 775036063dd5a..c83cf36982167 100644
--- a/bolt/lib/Rewrite/CMakeLists.txt
+++ b/bolt/lib/Rewrite/CMakeLists.txt
@@ -1,7 +1,6 @@
 set(LLVM_LINK_COMPONENTS
   Core
   DebugInfoDWARF
-  DebugInfoDWARFLowLevel
   JITLink
   MC
   Object
diff --git a/bolt/lib/Rewrite/DWARFRewriter.cpp 
b/bolt/lib/Rewrite/DWARFRewriter.cpp
index 0c1a1bac6c72e..9c9bdefe08429 100644
--- a/bolt/lib/Rewrite/DWARFRewriter.cpp
+++ b/bolt/lib/Rewrite/DWARFRewriter.cpp
@@ -24,10 +24,10 @@
 #include "llvm/DebugInfo/DWARF/DWARFContext.h"
 #include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h"
 #include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h"
+#include "llvm/DebugInfo/DWARF/DWARFExpression.h"
 #include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
 #include "llvm/DebugInfo/DWARF/DWARFTypeUnit.h"
 #include "llvm/DebugInfo/DWARF/DWARFUnit.h"
-#include "llvm/DebugInfo/DWARF/LowLevel/DWARFExpression.h"
 #include "llvm/MC/MCAsmBackend.h"
 #include "llvm/MC/MCAssembler.h"
 #include "llvm/MC/MCObjectWriter.h"
diff --git a/lldb/source/Expression/DWARFExpression.cpp 
b/lldb/source/Expression/DWARFExpression.cpp
index 2df27513a0b3f..661324338e801 100644
--- a/lldb/source/Expression/DWARFExpression.cpp
+++ b/lldb/source/Expression/DWARFExpression.cpp
@@ -36,8 +36,7 @@
 #include "lldb/Target/StackID.h"
 #include "lldb/Target/Target.h"
 #include "lldb/Target/Thread.h"
-#include "llvm/DebugInfo/DWARF/DWARFExpressionPrinter.h"
-#include "llvm/DebugInfo/DWARF/LowLevel/DWARFExpression.h"
+#include "llvm/DebugInfo/DWARF/DWARFExpression.h"
 
 using namespace lldb;
 using namespace lldb_private;
@@ -82,7 +81,7 @@ void DWARFExpression::DumpLocation(Stream *s, 
lldb::DescriptionLevel level,
   llvm::DIDumpOptions DumpOpts;
   DumpOpts.GetNameForDWARFReg = GetRegName;
   llvm::DWARFExpression E(m_data.GetAsLLVM(), m_data.GetAddressByteSize());
-  llvm::printDwarfExpression(&E, s->AsRawOstream(), DumpOpts, nullptr);
+  llvm::DWARFExpressionPrinter::print(&E, s->AsRawOstream(), DumpOpts, 
nullptr);
 }
 
 RegisterKind DWARFExpression::GetRegisterKind() const { return m_reg_kind; }
diff --git a/lldb/source/Symbol/UnwindPlan.cpp 
b/lldb/source/Symbol/UnwindPlan.cpp
index 9245e52732061..e9ac6b6cde295 100644
--- a/lldb/source/Symbol/UnwindPlan.cpp
+++ b/lldb/source/Symbol/UnwindPlan.cpp
@@ -17,8 +17,7 @@
 #include "lldb/Utility/Log.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/DebugInfo/DIContext.h"
-#include "llvm/DebugInfo/DWARF/DWARFExpressionPrinter.h"
-#include "llvm/DebugInfo/DWARF/LowLevel/DWARFExpression.h"
+#include "llvm/DebugInfo/DWARF/DWARFExpression.h"
 #include <optional>
 
 using namespace lldb;
@@ -90,7 +89,8 @@ static void DumpDWARFExpr(Stream &s, llvm::ArrayRef<uint8_t> 
expr, Thread *threa
                              order_and_width->second);
     llvm::DWARFExpression E(data, order_and_width->second,
                             llvm::dwarf::DWARF32);
-    printDwarfExpression(&E, s.AsRawOstream(), llvm::DIDumpOptions(), nullptr);
+    llvm::DWARFExpressionPrinter::print(&E, s.AsRawOstream(),
+                                        llvm::DIDumpOptions(), nullptr);
   } else
     s.PutCString("dwarf-expr");
 }
diff --git a/lldb/unittests/Symbol/PostfixExpressionTest.cpp 
b/lldb/unittests/Symbol/PostfixExpressionTest.cpp
index f60b5d2c389ed..1e437da5133d9 100644
--- a/lldb/unittests/Symbol/PostfixExpressionTest.cpp
+++ b/lldb/unittests/Symbol/PostfixExpressionTest.cpp
@@ -11,8 +11,7 @@
 #include "lldb/Utility/StreamString.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/DebugInfo/DIContext.h"
-#include "llvm/DebugInfo/DWARF/DWARFExpressionPrinter.h"
-#include "llvm/DebugInfo/DWARF/LowLevel/DWARFExpression.h"
+#include "llvm/DebugInfo/DWARF/DWARFExpression.h"
 #include "llvm/Support/FormatVariadic.h"
 #include "llvm/Support/raw_ostream.h"
 #include "gmock/gmock.h"
@@ -161,7 +160,7 @@ static std::string ParseAndGenerateDWARF(llvm::StringRef 
expr) {
   std::string result;
   llvm::raw_string_ostream os(result);
   llvm::DWARFExpression E(extractor, addr_size, llvm::dwarf::DWARF32);
-  llvm::printDwarfExpression(&E, os, llvm::DIDumpOptions(), nullptr);
+  llvm::DWARFExpressionPrinter::print(&E, os, llvm::DIDumpOptions(), nullptr);
   return result;
 }
 
diff --git 
a/lldb/unittests/SymbolFile/NativePDB/PdbFPOProgramToDWARFExpressionTests.cpp 
b/lldb/unittests/SymbolFile/NativePDB/PdbFPOProgramToDWARFExpressionTests.cpp
index c60688ef22939..d746e04f8a9fc 100644
--- 
a/lldb/unittests/SymbolFile/NativePDB/PdbFPOProgramToDWARFExpressionTests.cpp
+++ 
b/lldb/unittests/SymbolFile/NativePDB/PdbFPOProgramToDWARFExpressionTests.cpp
@@ -16,8 +16,7 @@
 #include "lldb/Utility/StreamBuffer.h"
 #include "lldb/Utility/StreamString.h"
 #include "llvm/DebugInfo/DIContext.h"
-#include "llvm/DebugInfo/DWARF/DWARFExpressionPrinter.h"
-#include "llvm/DebugInfo/DWARF/LowLevel/DWARFExpression.h"
+#include "llvm/DebugInfo/DWARF/DWARFExpression.h"
 
 using namespace lldb;
 using namespace lldb_private;
@@ -41,7 +40,7 @@ CheckValidProgramTranslation(llvm::StringRef fpo_program,
   std::string result;
   llvm::raw_string_ostream os(result);
   llvm::DWARFExpression E(extractor, /*AddressSize=*/4, llvm::dwarf::DWARF32);
-  llvm::printDwarfExpression(&E, os, llvm::DIDumpOptions(), nullptr);
+  llvm::DWARFExpressionPrinter::print(&E, os, llvm::DIDumpOptions(), nullptr);
 
   // actual check
   ASSERT_EQ(expected_dwarf_expression, result);
diff --git a/llvm/include/llvm/DWARFLinker/AddressesMap.h 
b/llvm/include/llvm/DWARFLinker/AddressesMap.h
index e2215c70dc34e..a232aafadc5ce 100644
--- a/llvm/include/llvm/DWARFLinker/AddressesMap.h
+++ b/llvm/include/llvm/DWARFLinker/AddressesMap.h
@@ -12,8 +12,8 @@
 #include "llvm/ADT/AddressRanges.h"
 #include "llvm/DebugInfo/DWARF/DWARFContext.h"
 #include "llvm/DebugInfo/DWARF/DWARFDie.h"
+#include "llvm/DebugInfo/DWARF/DWARFExpression.h"
 #include "llvm/DebugInfo/DWARF/DWARFUnit.h"
-#include "llvm/DebugInfo/DWARF/LowLevel/DWARFExpression.h"
 #include <cstdint>
 
 namespace llvm {
diff --git a/llvm/include/llvm/DWARFLinker/Classic/DWARFLinker.h 
b/llvm/include/llvm/DWARFLinker/Classic/DWARFLinker.h
index 5b9535380aebf..b12d96812108e 100644
--- a/llvm/include/llvm/DWARFLinker/Classic/DWARFLinker.h
+++ b/llvm/include/llvm/DWARFLinker/Classic/DWARFLinker.h
@@ -20,7 +20,7 @@
 #include "llvm/DebugInfo/DWARF/DWARFDebugLine.h"
 #include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h"
 #include "llvm/DebugInfo/DWARF/DWARFDie.h"
-#include "llvm/DebugInfo/DWARF/LowLevel/DWARFExpression.h"
+#include "llvm/DebugInfo/DWARF/DWARFExpression.h"
 #include "llvm/Support/Compiler.h"
 #include <map>
 
diff --git a/llvm/include/llvm/DWARFLinker/DWARFLinkerBase.h 
b/llvm/include/llvm/DWARFLinker/DWARFLinkerBase.h
index 99aeb0df076e6..17a18c4b029f4 100644
--- a/llvm/include/llvm/DWARFLinker/DWARFLinkerBase.h
+++ b/llvm/include/llvm/DWARFLinker/DWARFLinkerBase.h
@@ -16,7 +16,7 @@
 #include "llvm/DebugInfo/DWARF/DWARFDebugLine.h"
 #include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h"
 #include "llvm/DebugInfo/DWARF/DWARFDie.h"
-#include "llvm/DebugInfo/DWARF/LowLevel/DWARFExpression.h"
+#include "llvm/DebugInfo/DWARF/DWARFExpression.h"
 #include "llvm/Support/Compiler.h"
 #include <map>
 namespace llvm {
diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFCFIPrinter.h 
b/llvm/include/llvm/DebugInfo/DWARF/DWARFCFIPrinter.h
index 7d4bf8d923097..4723f00a4d241 100644
--- a/llvm/include/llvm/DebugInfo/DWARF/DWARFCFIPrinter.h
+++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFCFIPrinter.h
@@ -9,7 +9,7 @@
 #ifndef LLVM_DEBUGINFO_DWARF_DWARFCFIPRINTER_H
 #define LLVM_DEBUGINFO_DWARF_DWARFCFIPRINTER_H
 
-#include "llvm/DebugInfo/DWARF/LowLevel/DWARFCFIProgram.h"
+#include "llvm/DebugInfo/DWARF/DWARFCFIProgram.h"
 #include "llvm/Support/Compiler.h"
 
 namespace llvm {
diff --git a/llvm/include/llvm/DebugInfo/DWARF/LowLevel/DWARFCFIProgram.h 
b/llvm/include/llvm/DebugInfo/DWARF/DWARFCFIProgram.h
similarity index 50%
rename from llvm/include/llvm/DebugInfo/DWARF/LowLevel/DWARFCFIProgram.h
rename to llvm/include/llvm/DebugInfo/DWARF/DWARFCFIProgram.h
index bdad0b5ad7a5a..1d89ac3578c10 100644
--- a/llvm/include/llvm/DebugInfo/DWARF/LowLevel/DWARFCFIProgram.h
+++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFCFIProgram.h
@@ -12,8 +12,8 @@
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/iterator.h"
-#include "llvm/DebugInfo/DWARF/LowLevel/DWARFDataExtractorSimple.h"
-#include "llvm/DebugInfo/DWARF/LowLevel/DWARFExpression.h"
+#include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
+#include "llvm/DebugInfo/DWARF/DWARFExpression.h"
 #include "llvm/Support/Compiler.h"
 #include "llvm/Support/Error.h"
 #include "llvm/TargetParser/Triple.h"
@@ -78,150 +78,8 @@ class CFIProgram {
   /// starting at *Offset and ending at EndOffset. *Offset is updated
   /// to EndOffset upon successful parsing, or indicates the offset
   /// where a problem occurred in case an error is returned.
-  template <typename T>
-  LLVM_ABI Error parse(DWARFDataExtractorBase<T> &Data, uint64_t *Offset,
-                       uint64_t EndOffset) {
-    // See DWARF standard v3, section 7.23
-    const uint8_t DWARF_CFI_PRIMARY_OPCODE_MASK = 0xc0;
-    const uint8_t DWARF_CFI_PRIMARY_OPERAND_MASK = 0x3f;
-
-    DataExtractor::Cursor C(*Offset);
-    while (C && C.tell() < EndOffset) {
-      uint8_t Opcode = Data.getRelocatedValue(C, 1);
-      if (!C)
-        break;
-
-      // Some instructions have a primary opcode encoded in the top bits.
-      if (uint8_t Primary = Opcode & DWARF_CFI_PRIMARY_OPCODE_MASK) {
-        // If it's a primary opcode, the first operand is encoded in the
-        // bottom bits of the opcode itself.
-        uint64_t Op1 = Opcode & DWARF_CFI_PRIMARY_OPERAND_MASK;
-        switch (Primary) {
-        case DW_CFA_advance_loc:
-        case DW_CFA_restore:
-          addInstruction(Primary, Op1);
-          break;
-        case DW_CFA_offset:
-          addInstruction(Primary, Op1, Data.getULEB128(C));
-          break;
-        default:
-          llvm_unreachable("invalid primary CFI opcode");
-        }
-        continue;
-      }
-
-      // Extended opcode - its value is Opcode itself.
-      switch (Opcode) {
-      default:
-        return createStringError(errc::illegal_byte_sequence,
-                                 "invalid extended CFI opcode 0x%" PRIx8,
-                                 Opcode);
-      case DW_CFA_nop:
-      case DW_CFA_remember_state:
-      case DW_CFA_restore_state:
-      case DW_CFA_GNU_window_save:
-      case DW_CFA_AARCH64_negate_ra_state_with_pc:
-        // No operands
-        addInstruction(Opcode);
-        break;
-      case DW_CFA_set_loc:
-        // Operands: Address
-        addInstruction(Opcode, Data.getRelocatedAddress(C));
-        break;
-      case DW_CFA_advance_loc1:
-        // Operands: 1-byte delta
-        addInstruction(Opcode, Data.getRelocatedValue(C, 1));
-        break;
-      case DW_CFA_advance_loc2:
-        // Operands: 2-byte delta
-        addInstruction(Opcode, Data.getRelocatedValue(C, 2));
-        break;
-      case DW_CFA_advance_loc4:
-        // Operands: 4-byte delta
-        addInstruction(Opcode, Data.getRelocatedValue(C, 4));
-        break;
-      case DW_CFA_restore_extended:
-      case DW_CFA_undefined:
-      case DW_CFA_same_value:
-      case DW_CFA_def_cfa_register:
-      case DW_CFA_def_cfa_offset:
-      case DW_CFA_GNU_args_size:
-        // Operands: ULEB128
-        addInstruction(Opcode, Data.getULEB128(C));
-        break;
-      case DW_CFA_def_cfa_offset_sf:
-        // Operands: SLEB128
-        addInstruction(Opcode, Data.getSLEB128(C));
-        break;
-      case DW_CFA_LLVM_def_aspace_cfa:
-      case DW_CFA_LLVM_def_aspace_cfa_sf: {
-        auto RegNum = Data.getULEB128(C);
-        auto CfaOffset = Opcode == DW_CFA_LLVM_def_aspace_cfa
-                             ? Data.getULEB128(C)
-                             : Data.getSLEB128(C);
-        auto AddressSpace = Data.getULEB128(C);
-        addInstruction(Opcode, RegNum, CfaOffset, AddressSpace);
-        break;
-      }
-      case DW_CFA_offset_extended:
-      case DW_CFA_register:
-      case DW_CFA_def_cfa:
-      case DW_CFA_val_offset: {
-        // Operands: ULEB128, ULEB128
-        // Note: We can not embed getULEB128 directly into function
-        // argument list. getULEB128 changes Offset and order of evaluation
-        // for arguments is unspecified.
-        uint64_t op1 = Data.getULEB128(C);
-        uint64_t op2 = Data.getULEB128(C);
-        addInstruction(Opcode, op1, op2);
-        break;
-      }
-      case DW_CFA_offset_extended_sf:
-      case DW_CFA_def_cfa_sf:
-      case DW_CFA_val_offset_sf: {
-        // Operands: ULEB128, SLEB128
-        // Note: see comment for the previous case
-        uint64_t op1 = Data.getULEB128(C);
-        uint64_t op2 = (uint64_t)Data.getSLEB128(C);
-        addInstruction(Opcode, op1, op2);
-        break;
-      }
-      case DW_CFA_def_cfa_expression: {
-        uint64_t ExprLength = Data.getULEB128(C);
-        addInstruction(Opcode, 0);
-        StringRef Expression = Data.getBytes(C, ExprLength);
-
-        DataExtractor Extractor(Expression, Data.isLittleEndian(),
-                                Data.getAddressSize());
-        // Note. We do not pass the DWARF format to DWARFExpression, because
-        // DW_OP_call_ref, the only operation which depends on the format, is
-        // prohibited in call frame instructions, see sec. 6.4.2 in DWARFv5.
-        Instructions.back().Expression =
-            DWARFExpression(Extractor, Data.getAddressSize());
-        break;
-      }
-      case DW_CFA_expression:
-      case DW_CFA_val_expression: {
-        uint64_t RegNum = Data.getULEB128(C);
-        addInstruction(Opcode, RegNum, 0);
-
-        uint64_t BlockLength = Data.getULEB128(C);
-        StringRef Expression = Data.getBytes(C, BlockLength);
-        DataExtractor Extractor(Expression, Data.isLittleEndian(),
-                                Data.getAddressSize());
-        // Note. We do not pass the DWARF format to DWARFExpression, because
-        // DW_OP_call_ref, the only operation which depends on the format, is
-        // prohibited in call frame instructions, see sec. 6.4.2 in DWARFv5.
-        Instructions.back().Expression =
-            DWARFExpression(Extractor, Data.getAddressSize());
-        break;
-      }
-      }
-    }
-
-    *Offset = C.tell();
-    return C.takeError();
-  }
+  LLVM_ABI Error parse(DWARFDataExtractor Data, uint64_t *Offset,
+                       uint64_t EndOffset);
 
   void addInstruction(const Instruction &I) { Instructions.push_back(I); }
 
diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFDataExtractor.h 
b/llvm/include/llvm/DebugInfo/DWARF/DWARFDataExtractor.h
index def291046c7db..005ccd208cdda 100644
--- a/llvm/include/llvm/DebugInfo/DWARF/DWARFDataExtractor.h
+++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFDataExtractor.h
@@ -10,10 +10,10 @@
 #define LLVM_DEBUGINFO_DWARF_DWARFDATAEXTRACTOR_H
 
 #include "llvm/BinaryFormat/Dwarf.h"
+#include "llvm/DebugInfo/DWARF/DWARFDataExtractorSimple.h"
 #include "llvm/DebugInfo/DWARF/DWARFObject.h"
 #include "llvm/DebugInfo/DWARF/DWARFRelocMap.h"
 #include "llvm/DebugInfo/DWARF/DWARFSection.h"
-#include "llvm/DebugInfo/DWARF/LowLevel/DWARFDataExtractorSimple.h"
 #include "llvm/Support/Compiler.h"
 
 namespace llvm {
diff --git 
a/llvm/include/llvm/DebugInfo/DWARF/LowLevel/DWARFDataExtractorSimple.h 
b/llvm/include/llvm/DebugInfo/DWARF/DWARFDataExtractorSimple.h
similarity index 100%
rename from 
llvm/include/llvm/DebugInfo/DWARF/LowLevel/DWARFDataExtractorSimple.h
rename to llvm/include/llvm/DebugInfo/DWARF/DWARFDataExtractorSimple.h
diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h 
b/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h
index e0d60f605964f..3b367009a379d 100644
--- a/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h
+++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h
@@ -12,8 +12,8 @@
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/iterator.h"
-#include "llvm/DebugInfo/DWARF/LowLevel/DWARFCFIProgram.h"
-#include "llvm/DebugInfo/DWARF/LowLevel/DWARFExpression.h"
+#include "llvm/DebugInfo/DWARF/DWARFCFIProgram.h"
+#include "llvm/DebugInfo/DWARF/DWARFExpression.h"
 #include "llvm/Support/Compiler.h"
 #include "llvm/Support/Error.h"
 #include "llvm/TargetParser/Triple.h"
diff --git a/llvm/include/llvm/DebugInfo/DWARF/LowLevel/DWARFExpression.h 
b/llvm/include/llvm/DebugInfo/DWARF/DWARFExpression.h
similarity index 67%
rename from llvm/include/llvm/DebugInfo/DWARF/LowLevel/DWARFExpression.h
rename to llvm/include/llvm/DebugInfo/DWARF/DWARFExpression.h
index 06840b20f9690..ea414278c35d6 100644
--- a/llvm/include/llvm/DebugInfo/DWARF/LowLevel/DWARFExpression.h
+++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFExpression.h
@@ -65,7 +65,7 @@ class DWARFExpression {
 
     /// Description of the encoding of one expression Op.
     struct Description {
-      DwarfVersion Version;     ///< Dwarf version where the Op was introduced.
+      DwarfVersion Version; ///< Dwarf version where the Op was introduced.
       SmallVector<Encoding> Op; ///< Encoding for Op operands.
 
       template <typename... Ts>
@@ -77,6 +77,7 @@ class DWARFExpression {
 
   private:
     friend class DWARFExpression::iterator;
+    friend class DWARFExpressionPrinter;
     friend class DWARFVerifier;
 
     uint8_t Opcode; ///< The Op Opcode, DW_OP_<something>.
@@ -155,6 +156,7 @@ class DWARFExpression {
 
   StringRef getData() const { return Data.getData(); }
 
+  friend class DWARFExpressionPrinter;
   friend class DWARFVerifier;
 
 private:
@@ -168,6 +170,65 @@ inline bool operator==(const DWARFExpression::iterator 
&LHS,
   return LHS.Expr == RHS.Expr && LHS.Offset == RHS.Offset;
 }
 
+// This functionality is separated from the main data structure so that nothing
+// in DWARFExpression.cpp needs build-time dependencies on DWARFUnit or other
+// higher-level Dwarf structures. This approach creates better layering and
+// allows DWARFExpression to be used from code which can't have dependencies on
+// those higher-level structures.
+
+class DWARFUnit;
+struct DIDumpOptions;
+class raw_ostream;
+
+class DWARFExpressionPrinter {
+public:
+  /// Print a Dwarf expression/
+  /// \param E to be printed
+  /// \param OS to this stream
+  /// \param GetNameForDWARFReg callback to return dwarf register name
+  LLVM_ABI static void print(const DWARFExpression *E, raw_ostream &OS,
+                             DIDumpOptions DumpOpts, DWARFUnit *U,
+                             bool IsEH = false);
+
+  /// Print the expression in a format intended to be compact and useful to a
+  /// user, but not perfectly unambiguous, or capable of representing every
+  /// valid DWARF expression. Returns true if the expression was sucessfully
+  /// printed.
+  ///
+  /// \param E to be printed
+  /// \param OS to this stream
+  /// \param GetNameForDWARFReg callback to return dwarf register name
+  ///
+  /// \returns true if the expression was successfully printed
+  LLVM_ABI static bool printCompact(
+      const DWARFExpression *E, raw_ostream &OS,
+      std::function<StringRef(uint64_t RegNum, bool IsEH)> GetNameForDWARFReg =
+          nullptr);
+
+  /// Pretty print a register opcode and operands.
+  /// \param U within the context of this Dwarf unit, if any.
+  /// \param OS to this stream
+  /// \param DumpOpts with these options
+  /// \param Opcode to print
+  /// \param Operands to the opcode
+  ///
+  /// returns true if the Op was successfully printed
+  LLVM_ABI static bool prettyPrintRegisterOp(DWARFUnit *U, raw_ostream &OS,
+                                             DIDumpOptions DumpOpts,
+                                             uint8_t Opcode,
+                                             ArrayRef<uint64_t> Operands);
+
+private:
+  static bool printOp(const DWARFExpression::Operation *Op, raw_ostream &OS,
+                      DIDumpOptions DumpOpts, const DWARFExpression *Expr,
+                      DWARFUnit *U);
+
+  static void prettyPrintBaseTypeRef(DWARFUnit *U, raw_ostream &OS,
+                                     DIDumpOptions DumpOpts,
+                                     ArrayRef<uint64_t> Operands,
+                                     unsigned Operand);
+};
+
 } // end namespace llvm
 
 #endif // LLVM_DEBUGINFO_DWARF_DWARFEXPRESSION_H
diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFExpressionPrinter.h 
b/llvm/include/llvm/DebugInfo/DWARF/DWARFExpressionPrinter.h
deleted file mode 100644
index 0aad492d47551..0000000000000
--- a/llvm/include/llvm/DebugInfo/DWARF/DWARFExpressionPrinter.h
+++ /dev/null
@@ -1,66 +0,0 @@
-//===--- DWARFExpressionPRinter.h - DWARF Expression Printing ---*- C++ 
-*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_DEBUGINFO_DWARF_DWARFEXPRESSIONPRINTER_H
-#define LLVM_DEBUGINFO_DWARF_DWARFEXPRESSIONPRINTER_H
-
-#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/iterator.h"
-#include "llvm/DebugInfo/DWARF/LowLevel/DWARFExpression.h"
-#include "llvm/Support/Compiler.h"
-
-namespace llvm {
-
-// This functionality is separated from the main data structure so that nothing
-// in DWARFExpression.cpp needs build-time dependencies on DWARFUnit or other
-// higher-level Dwarf structures. This approach creates better layering and
-// allows DWARFExpression to be used from code which can't have dependencies on
-// those higher-level structures.
-
-class DWARFUnit;
-struct DIDumpOptions;
-class raw_ostream;
-
-/// Print a Dwarf expression/
-/// \param E to be printed
-/// \param OS to this stream
-/// \param GetNameForDWARFReg callback to return dwarf register name
-LLVM_ABI void printDwarfExpression(const DWARFExpression *E, raw_ostream &OS,
-                                   DIDumpOptions DumpOpts, DWARFUnit *U,
-                                   bool IsEH = false);
-
-/// Print the expression in a format intended to be compact and useful to a
-/// user, but not perfectly unambiguous, or capable of representing every
-/// valid DWARF expression. Returns true if the expression was sucessfully
-/// printed.
-///
-/// \param E to be printed
-/// \param OS to this stream
-/// \param GetNameForDWARFReg callback to return dwarf register name
-///
-/// \returns true if the expression was successfully printed
-LLVM_ABI bool printDwarfExpressionCompact(
-    const DWARFExpression *E, raw_ostream &OS,
-    std::function<StringRef(uint64_t RegNum, bool IsEH)> GetNameForDWARFReg =
-        nullptr);
-
-/// Pretty print a register opcode and operands.
-/// \param U within the context of this Dwarf unit, if any.
-/// \param OS to this stream
-/// \param DumpOpts with these options
-/// \param Opcode to print
-/// \param Operands to the opcode
-///
-/// returns true if the Op was successfully printed
-LLVM_ABI bool prettyPrintRegisterOp(DWARFUnit *U, raw_ostream &OS,
-                                    DIDumpOptions DumpOpts, uint8_t Opcode,
-                                    ArrayRef<uint64_t> Operands);
-
-} // end namespace llvm
-
-#endif // LLVM_DEBUGINFO_DWARF_DWARFEXPRESSIONPRINTER_H
diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFVerifier.h 
b/llvm/include/llvm/DebugInfo/DWARF/DWARFVerifier.h
index f667496ab1059..8e1b9589a5d76 100644
--- a/llvm/include/llvm/DebugInfo/DWARF/DWARFVerifier.h
+++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFVerifier.h
@@ -14,8 +14,8 @@
 #include "llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h"
 #include "llvm/DebugInfo/DWARF/DWARFAddressRange.h"
 #include "llvm/DebugInfo/DWARF/DWARFDie.h"
+#include "llvm/DebugInfo/DWARF/DWARFExpression.h"
 #include "llvm/DebugInfo/DWARF/DWARFUnitIndex.h"
-#include "llvm/DebugInfo/DWARF/LowLevel/DWARFExpression.h"
 #include "llvm/Support/Compiler.h"
 #include <cstdint>
 #include <map>
diff --git a/llvm/lib/CodeGen/AsmPrinter/CMakeLists.txt 
b/llvm/lib/CodeGen/AsmPrinter/CMakeLists.txt
index 34969d7524890..0fe4b905831ff 100644
--- a/llvm/lib/CodeGen/AsmPrinter/CMakeLists.txt
+++ b/llvm/lib/CodeGen/AsmPrinter/CMakeLists.txt
@@ -38,7 +38,6 @@ add_llvm_component_library(LLVMAsmPrinter
   Core
   DebugInfoCodeView
   DebugInfoDWARF
-  DebugInfoDWARFLowLevel
   MC
   MCParser
   Remarks
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp 
b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
index ca419a8db18ae..0edfca78b0886 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp
@@ -32,7 +32,7 @@
 #include "llvm/CodeGen/TargetRegisterInfo.h"
 #include "llvm/CodeGen/TargetSubtargetInfo.h"
 #include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
-#include "llvm/DebugInfo/DWARF/LowLevel/DWARFExpression.h"
+#include "llvm/DebugInfo/DWARF/DWARFExpression.h"
 #include "llvm/IR/Constants.h"
 #include "llvm/IR/DebugInfoMetadata.h"
 #include "llvm/IR/Function.h"
diff --git a/llvm/lib/DWARFLinker/Classic/CMakeLists.txt 
b/llvm/lib/DWARFLinker/Classic/CMakeLists.txt
index 4e5cb3c6dfb51..5d3b259e4a33a 100644
--- a/llvm/lib/DWARFLinker/Classic/CMakeLists.txt
+++ b/llvm/lib/DWARFLinker/Classic/CMakeLists.txt
@@ -19,7 +19,6 @@ add_llvm_component_library(LLVMDWARFLinkerClassic
   CodeGen
   CodeGenTypes
   DebugInfoDWARF
-  DebugInfoDWARFLowLevel
   DWARFLinker
   MC
   Object
diff --git a/llvm/lib/DWARFLinker/Classic/DWARFLinker.cpp 
b/llvm/lib/DWARFLinker/Classic/DWARFLinker.cpp
index 222dc88098102..ae4cc6d85c120 100644
--- a/llvm/lib/DWARFLinker/Classic/DWARFLinker.cpp
+++ b/llvm/lib/DWARFLinker/Classic/DWARFLinker.cpp
@@ -23,10 +23,10 @@
 #include "llvm/DebugInfo/DWARF/DWARFDebugMacro.h"
 #include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h"
 #include "llvm/DebugInfo/DWARF/DWARFDie.h"
+#include "llvm/DebugInfo/DWARF/DWARFExpression.h"
 #include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
 #include "llvm/DebugInfo/DWARF/DWARFSection.h"
 #include "llvm/DebugInfo/DWARF/DWARFUnit.h"
-#include "llvm/DebugInfo/DWARF/LowLevel/DWARFExpression.h"
 #include "llvm/MC/MCDwarf.h"
 #include "llvm/Support/DataExtractor.h"
 #include "llvm/Support/Error.h"
diff --git a/llvm/lib/DWARFLinker/Classic/DWARFLinkerCompileUnit.cpp 
b/llvm/lib/DWARFLinker/Classic/DWARFLinkerCompileUnit.cpp
index 027363aa394e0..66bf158e60f1d 100644
--- a/llvm/lib/DWARFLinker/Classic/DWARFLinkerCompileUnit.cpp
+++ b/llvm/lib/DWARFLinker/Classic/DWARFLinkerCompileUnit.cpp
@@ -10,7 +10,7 @@
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/DWARFLinker/Classic/DWARFLinkerDeclContext.h"
 #include "llvm/DebugInfo/DWARF/DWARFContext.h"
-#include "llvm/DebugInfo/DWARF/LowLevel/DWARFExpression.h"
+#include "llvm/DebugInfo/DWARF/DWARFExpression.h"
 #include "llvm/Support/FormatVariadic.h"
 
 namespace llvm {
diff --git a/llvm/lib/DebugInfo/DWARF/CMakeLists.txt 
b/llvm/lib/DebugInfo/DWARF/CMakeLists.txt
index ce426aeba3f3f..86e74110b15ea 100644
--- a/llvm/lib/DebugInfo/DWARF/CMakeLists.txt
+++ b/llvm/lib/DebugInfo/DWARF/CMakeLists.txt
@@ -1,10 +1,9 @@
-add_subdirectory(LowLevel)
-
 add_llvm_component_library(LLVMDebugInfoDWARF
   DWARFAbbreviationDeclaration.cpp
   DWARFAddressRange.cpp
   DWARFAcceleratorTable.cpp
   DWARFCFIPrinter.cpp
+  DWARFCFIProgram.cpp
   DWARFCompileUnit.cpp
   DWARFContext.cpp
   DWARFDebugAbbrev.cpp
@@ -20,7 +19,7 @@ add_llvm_component_library(LLVMDebugInfoDWARF
   DWARFDebugRangeList.cpp
   DWARFDebugRnglists.cpp
   DWARFDie.cpp
-  DWARFExpressionPrinter.cpp
+  DWARFExpression.cpp
   DWARFFormValue.cpp
   DWARFGdbIndex.cpp
   DWARFListTable.cpp
@@ -36,7 +35,6 @@ add_llvm_component_library(LLVMDebugInfoDWARF
 
   LINK_COMPONENTS
   BinaryFormat
-  DebugInfoDWARFLowLevel
   Object
   Support
   TargetParser
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFCFIPrinter.cpp 
b/llvm/lib/DebugInfo/DWARF/DWARFCFIPrinter.cpp
index 2abab0277a9f6..e52f671e4fa1c 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFCFIPrinter.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFCFIPrinter.cpp
@@ -8,9 +8,8 @@
 
 #include "llvm/DebugInfo/DWARF/DWARFCFIPrinter.h"
 #include "llvm/DebugInfo/DIContext.h"
+#include "llvm/DebugInfo/DWARF/DWARFCFIProgram.h"
 #include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
-#include "llvm/DebugInfo/DWARF/DWARFExpressionPrinter.h"
-#include "llvm/DebugInfo/DWARF/LowLevel/DWARFCFIProgram.h"
 #include "llvm/Support/Compiler.h"
 #include "llvm/Support/DataExtractor.h"
 #include "llvm/Support/Errc.h"
@@ -101,7 +100,8 @@ static void printOperand(raw_ostream &OS, const 
DIDumpOptions &DumpOpts,
   case CFIProgram::OT_Expression:
     assert(Instr.Expression && "missing DWARFExpression object");
     OS << " ";
-    printDwarfExpression(&Instr.Expression.value(), OS, DumpOpts, nullptr);
+    DWARFExpressionPrinter::print(&Instr.Expression.value(), OS, DumpOpts,
+                                  nullptr);
     break;
   }
 }
diff --git a/llvm/lib/DebugInfo/DWARF/LowLevel/DWARFCFIProgram.cpp 
b/llvm/lib/DebugInfo/DWARF/DWARFCFIProgram.cpp
similarity index 60%
rename from llvm/lib/DebugInfo/DWARF/LowLevel/DWARFCFIProgram.cpp
rename to llvm/lib/DebugInfo/DWARF/DWARFCFIProgram.cpp
index 25a0ccb50c8a9..365b26b98a1e3 100644
--- a/llvm/lib/DebugInfo/DWARF/LowLevel/DWARFCFIProgram.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFCFIProgram.cpp
@@ -6,8 +6,9 @@
 //
 
//===----------------------------------------------------------------------===//
 
-#include "llvm/DebugInfo/DWARF/LowLevel/DWARFCFIProgram.h"
-#include "llvm/DebugInfo/DWARF/LowLevel/DWARFDataExtractorSimple.h"
+#include "llvm/DebugInfo/DWARF/DWARFCFIProgram.h"
+#include "llvm/DebugInfo/DIContext.h"
+#include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
 #include "llvm/Support/Compiler.h"
 #include "llvm/Support/DataExtractor.h"
 #include "llvm/Support/Errc.h"
@@ -22,6 +23,149 @@
 using namespace llvm;
 using namespace dwarf;
 
+// See DWARF standard v3, section 7.23
+const uint8_t DWARF_CFI_PRIMARY_OPCODE_MASK = 0xc0;
+const uint8_t DWARF_CFI_PRIMARY_OPERAND_MASK = 0x3f;
+
+Error CFIProgram::parse(DWARFDataExtractor Data, uint64_t *Offset,
+                        uint64_t EndOffset) {
+  DataExtractor::Cursor C(*Offset);
+  while (C && C.tell() < EndOffset) {
+    uint8_t Opcode = Data.getRelocatedValue(C, 1);
+    if (!C)
+      break;
+
+    // Some instructions have a primary opcode encoded in the top bits.
+    if (uint8_t Primary = Opcode & DWARF_CFI_PRIMARY_OPCODE_MASK) {
+      // If it's a primary opcode, the first operand is encoded in the bottom
+      // bits of the opcode itself.
+      uint64_t Op1 = Opcode & DWARF_CFI_PRIMARY_OPERAND_MASK;
+      switch (Primary) {
+      case DW_CFA_advance_loc:
+      case DW_CFA_restore:
+        addInstruction(Primary, Op1);
+        break;
+      case DW_CFA_offset:
+        addInstruction(Primary, Op1, Data.getULEB128(C));
+        break;
+      default:
+        llvm_unreachable("invalid primary CFI opcode");
+      }
+      continue;
+    }
+
+    // Extended opcode - its value is Opcode itself.
+    switch (Opcode) {
+    default:
+      return createStringError(errc::illegal_byte_sequence,
+                               "invalid extended CFI opcode 0x%" PRIx8, 
Opcode);
+    case DW_CFA_nop:
+    case DW_CFA_remember_state:
+    case DW_CFA_restore_state:
+    case DW_CFA_GNU_window_save:
+    case DW_CFA_AARCH64_negate_ra_state_with_pc:
+      // No operands
+      addInstruction(Opcode);
+      break;
+    case DW_CFA_set_loc:
+      // Operands: Address
+      addInstruction(Opcode, Data.getRelocatedAddress(C));
+      break;
+    case DW_CFA_advance_loc1:
+      // Operands: 1-byte delta
+      addInstruction(Opcode, Data.getRelocatedValue(C, 1));
+      break;
+    case DW_CFA_advance_loc2:
+      // Operands: 2-byte delta
+      addInstruction(Opcode, Data.getRelocatedValue(C, 2));
+      break;
+    case DW_CFA_advance_loc4:
+      // Operands: 4-byte delta
+      addInstruction(Opcode, Data.getRelocatedValue(C, 4));
+      break;
+    case DW_CFA_restore_extended:
+    case DW_CFA_undefined:
+    case DW_CFA_same_value:
+    case DW_CFA_def_cfa_register:
+    case DW_CFA_def_cfa_offset:
+    case DW_CFA_GNU_args_size:
+      // Operands: ULEB128
+      addInstruction(Opcode, Data.getULEB128(C));
+      break;
+    case DW_CFA_def_cfa_offset_sf:
+      // Operands: SLEB128
+      addInstruction(Opcode, Data.getSLEB128(C));
+      break;
+    case DW_CFA_LLVM_def_aspace_cfa:
+    case DW_CFA_LLVM_def_aspace_cfa_sf: {
+      auto RegNum = Data.getULEB128(C);
+      auto CfaOffset = Opcode == DW_CFA_LLVM_def_aspace_cfa
+                           ? Data.getULEB128(C)
+                           : Data.getSLEB128(C);
+      auto AddressSpace = Data.getULEB128(C);
+      addInstruction(Opcode, RegNum, CfaOffset, AddressSpace);
+      break;
+    }
+    case DW_CFA_offset_extended:
+    case DW_CFA_register:
+    case DW_CFA_def_cfa:
+    case DW_CFA_val_offset: {
+      // Operands: ULEB128, ULEB128
+      // Note: We can not embed getULEB128 directly into function
+      // argument list. getULEB128 changes Offset and order of evaluation
+      // for arguments is unspecified.
+      uint64_t op1 = Data.getULEB128(C);
+      uint64_t op2 = Data.getULEB128(C);
+      addInstruction(Opcode, op1, op2);
+      break;
+    }
+    case DW_CFA_offset_extended_sf:
+    case DW_CFA_def_cfa_sf:
+    case DW_CFA_val_offset_sf: {
+      // Operands: ULEB128, SLEB128
+      // Note: see comment for the previous case
+      uint64_t op1 = Data.getULEB128(C);
+      uint64_t op2 = (uint64_t)Data.getSLEB128(C);
+      addInstruction(Opcode, op1, op2);
+      break;
+    }
+    case DW_CFA_def_cfa_expression: {
+      uint64_t ExprLength = Data.getULEB128(C);
+      addInstruction(Opcode, 0);
+      StringRef Expression = Data.getBytes(C, ExprLength);
+
+      DataExtractor Extractor(Expression, Data.isLittleEndian(),
+                              Data.getAddressSize());
+      // Note. We do not pass the DWARF format to DWARFExpression, because
+      // DW_OP_call_ref, the only operation which depends on the format, is
+      // prohibited in call frame instructions, see sec. 6.4.2 in DWARFv5.
+      Instructions.back().Expression =
+          DWARFExpression(Extractor, Data.getAddressSize());
+      break;
+    }
+    case DW_CFA_expression:
+    case DW_CFA_val_expression: {
+      uint64_t RegNum = Data.getULEB128(C);
+      addInstruction(Opcode, RegNum, 0);
+
+      uint64_t BlockLength = Data.getULEB128(C);
+      StringRef Expression = Data.getBytes(C, BlockLength);
+      DataExtractor Extractor(Expression, Data.isLittleEndian(),
+                              Data.getAddressSize());
+      // Note. We do not pass the DWARF format to DWARFExpression, because
+      // DW_OP_call_ref, the only operation which depends on the format, is
+      // prohibited in call frame instructions, see sec. 6.4.2 in DWARFv5.
+      Instructions.back().Expression =
+          DWARFExpression(Extractor, Data.getAddressSize());
+      break;
+    }
+    }
+  }
+
+  *Offset = C.tell();
+  return C.takeError();
+}
+
 StringRef CFIProgram::callFrameString(unsigned Opcode) const {
   return dwarf::CallFrameString(Opcode, Arch);
 }
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp 
b/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp
index 2bf88c9574c2d..9184502adc7cf 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp
@@ -13,10 +13,9 @@
 #include "llvm/BinaryFormat/Dwarf.h"
 #include "llvm/DebugInfo/DIContext.h"
 #include "llvm/DebugInfo/DWARF/DWARFCFIPrinter.h"
+#include "llvm/DebugInfo/DWARF/DWARFCFIProgram.h"
 #include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
-#include "llvm/DebugInfo/DWARF/DWARFExpressionPrinter.h"
-#include "llvm/DebugInfo/DWARF/LowLevel/DWARFCFIProgram.h"
-#include "llvm/DebugInfo/DWARF/LowLevel/DWARFExpression.h"
+#include "llvm/DebugInfo/DWARF/DWARFExpression.h"
 #include "llvm/Support/Compiler.h"
 #include "llvm/Support/DataExtractor.h"
 #include "llvm/Support/Errc.h"
@@ -115,7 +114,7 @@ void UnwindLocation::dump(raw_ostream &OS, DIDumpOptions 
DumpOpts) const {
     break;
   case DWARFExpr: {
     if (Expr)
-      printDwarfExpression(&Expr.value(), OS, DumpOpts, nullptr);
+      DWARFExpressionPrinter::print(&(*Expr), OS, DumpOpts, nullptr);
     break;
   }
   case Constant:
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp 
b/llvm/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp
index 5bd2427da7d73..fc71be32fdd79 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp
@@ -11,11 +11,10 @@
 #include "llvm/BinaryFormat/Dwarf.h"
 #include "llvm/DebugInfo/DIContext.h"
 #include "llvm/DebugInfo/DWARF/DWARFAddressRange.h"
-#include "llvm/DebugInfo/DWARF/DWARFExpressionPrinter.h"
+#include "llvm/DebugInfo/DWARF/DWARFExpression.h"
 #include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
 #include "llvm/DebugInfo/DWARF/DWARFLocationExpression.h"
 #include "llvm/DebugInfo/DWARF/DWARFUnit.h"
-#include "llvm/DebugInfo/DWARF/LowLevel/DWARFExpression.h"
 #include "llvm/Support/Format.h"
 #include "llvm/Support/raw_ostream.h"
 #include <algorithm>
@@ -118,7 +117,7 @@ static void dumpExpression(raw_ostream &OS, DIDumpOptions 
DumpOpts,
   if (U)
     Format = U->getFormat();
   DWARFExpression E(Extractor, AddressSize, Format);
-  printDwarfExpression(&E, OS, DumpOpts, U);
+  DWARFExpressionPrinter::print(&E, OS, DumpOpts, U);
 }
 
 bool DWARFLocationTable::dumpLocationList(
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp 
b/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp
index edc69a36cdff2..08dd9d30812d1 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp
@@ -15,12 +15,11 @@
 #include "llvm/DebugInfo/DWARF/DWARFContext.h"
 #include "llvm/DebugInfo/DWARF/DWARFDebugLine.h"
 #include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h"
-#include "llvm/DebugInfo/DWARF/DWARFExpressionPrinter.h"
+#include "llvm/DebugInfo/DWARF/DWARFExpression.h"
 #include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
 #include "llvm/DebugInfo/DWARF/DWARFTypePrinter.h"
 #include "llvm/DebugInfo/DWARF/DWARFTypeUnit.h"
 #include "llvm/DebugInfo/DWARF/DWARFUnit.h"
-#include "llvm/DebugInfo/DWARF/LowLevel/DWARFExpression.h"
 #include "llvm/Object/ObjectFile.h"
 #include "llvm/Support/DataExtractor.h"
 #include "llvm/Support/Format.h"
@@ -100,7 +99,7 @@ static void dumpLocationExpr(raw_ostream &OS, const 
DWARFFormValue &FormValue,
   DataExtractor Data(StringRef((const char *)Expr.data(), Expr.size()),
                      Ctx.isLittleEndian(), 0);
   DWARFExpression DE(Data, U->getAddressByteSize(), U->getFormParams().Format);
-  printDwarfExpression(&DE, OS, DumpOpts, U);
+  DWARFExpressionPrinter::print(&DE, OS, DumpOpts, U);
 }
 
 static DWARFDie resolveReferencedType(DWARFDie D, DWARFFormValue F) {
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFExpression.cpp 
b/llvm/lib/DebugInfo/DWARF/DWARFExpression.cpp
new file mode 100644
index 0000000000000..8255e013a2d79
--- /dev/null
+++ b/llvm/lib/DebugInfo/DWARF/DWARFExpression.cpp
@@ -0,0 +1,538 @@
+//===-- DWARFExpression.cpp 
-----------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/DWARF/DWARFExpression.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/DebugInfo/DWARF/DWARFUnit.h"
+#include "llvm/Support/Format.h"
+#include <cassert>
+#include <cstdint>
+#include <vector>
+
+using namespace llvm;
+using namespace dwarf;
+
+namespace llvm {
+
+typedef DWARFExpression::Operation Op;
+typedef Op::Description Desc;
+
+static std::vector<Desc> getOpDescriptions() {
+  std::vector<Desc> Descriptions;
+  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_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);
+  Descriptions[DW_OP_skip] = Desc(Op::Dwarf2, Op::SignedSize2);
+  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::Dwarf4, Op::SizeLEB, Op::SizeBlock);
+  Descriptions[DW_OP_stack_value] = Desc(Op::Dwarf4);
+  Descriptions[DW_OP_implicit_pointer] =
+      Desc(Op::Dwarf5, Op::SizeRefAddr, Op::SignedSizeLEB);
+  Descriptions[DW_OP_addrx] = Desc(Op::Dwarf5, Op::SizeLEB);
+  Descriptions[DW_OP_constx] = Desc(Op::Dwarf5, Op::SizeLEB);
+  Descriptions[DW_OP_entry_value] = Desc(Op::Dwarf5, Op::SizeLEB);
+  Descriptions[DW_OP_convert] = Desc(Op::Dwarf5, Op::BaseTypeRef);
+  Descriptions[DW_OP_regval_type] =
+      Desc(Op::Dwarf5, Op::SizeLEB, Op::BaseTypeRef);
+  Descriptions[DW_OP_WASM_location] =
+      Desc(Op::Dwarf4, Op::SizeLEB, Op::WasmLocationArg);
+  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);
+  Descriptions[DW_OP_GNU_entry_value] = Desc(Op::Dwarf4, Op::SizeLEB);
+  Descriptions[DW_OP_GNU_implicit_pointer] =
+      Desc(Op::Dwarf4, Op::SizeRefAddr, Op::SignedSizeLEB);
+  // This Description acts as a marker that getSubOpDesc must be called
+  // to fetch the final Description for the operation. Each such final
+  // Description must share the same first SizeSubOpLEB operand.
+  Descriptions[DW_OP_LLVM_user] = Desc(Op::Dwarf5, Op::SizeSubOpLEB);
+  return Descriptions;
+}
+
+static Desc getDescImpl(ArrayRef<Desc> Descriptions, unsigned Opcode) {
+  // Handle possible corrupted or unsupported operation.
+  if (Opcode >= Descriptions.size())
+    return {};
+  return Descriptions[Opcode];
+}
+
+static Desc getOpDesc(unsigned Opcode) {
+  static std::vector<Desc> Descriptions = getOpDescriptions();
+  return getDescImpl(Descriptions, Opcode);
+}
+
+static std::vector<Desc> getSubOpDescriptions() {
+  static constexpr unsigned LlvmUserDescriptionsSize = 1
+#define HANDLE_DW_OP_LLVM_USEROP(ID, NAME) +1
+#include "llvm/BinaryFormat/Dwarf.def"
+      ;
+  std::vector<Desc> Descriptions;
+  Descriptions.resize(LlvmUserDescriptionsSize);
+  Descriptions[DW_OP_LLVM_nop] = Desc(Op::Dwarf5, Op::SizeSubOpLEB);
+  return Descriptions;
+}
+
+static Desc getSubOpDesc(unsigned Opcode, unsigned SubOpcode) {
+  assert(Opcode == DW_OP_LLVM_user);
+  static std::vector<Desc> Descriptions = getSubOpDescriptions();
+  return getDescImpl(Descriptions, SubOpcode);
+}
+
+bool DWARFExpression::Operation::extract(DataExtractor Data,
+                                         uint8_t AddressSize, uint64_t Offset,
+                                         std::optional<DwarfFormat> Format) {
+  EndOffset = Offset;
+  Opcode = Data.getU8(&Offset);
+
+  Desc = getOpDesc(Opcode);
+  if (Desc.Version == Operation::DwarfNA)
+    return false;
+
+  Operands.resize(Desc.Op.size());
+  OperandEndOffsets.resize(Desc.Op.size());
+  for (unsigned Operand = 0; Operand < Desc.Op.size(); ++Operand) {
+    unsigned Size = Desc.Op[Operand];
+    unsigned Signed = Size & Operation::SignBit;
+
+    switch (Size & ~Operation::SignBit) {
+    case Operation::SizeSubOpLEB:
+      assert(Operand == 0 && "SubOp operand must be the first operand");
+      Operands[Operand] = Data.getULEB128(&Offset);
+      Desc = getSubOpDesc(Opcode, Operands[Operand]);
+      if (Desc.Version == Operation::DwarfNA)
+        return false;
+      assert(Desc.Op[Operand] == Operation::SizeSubOpLEB &&
+             "SizeSubOpLEB Description must begin with SizeSubOpLEB operand");
+      break;
+    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:
+      Operands[Operand] = Data.getUnsigned(&Offset, AddressSize);
+      break;
+    case Operation::SizeRefAddr:
+      if (!Format)
+        return false;
+      Operands[Operand] =
+          Data.getUnsigned(&Offset, dwarf::getDwarfOffsetByteSize(*Format));
+      break;
+    case Operation::SizeLEB:
+      if (Signed)
+        Operands[Operand] = Data.getSLEB128(&Offset);
+      else
+        Operands[Operand] = Data.getULEB128(&Offset);
+      break;
+    case Operation::BaseTypeRef:
+      Operands[Operand] = Data.getULEB128(&Offset);
+      break;
+    case Operation::WasmLocationArg:
+      assert(Operand == 1);
+      switch (Operands[0]) {
+      case 0:
+      case 1:
+      case 2:
+      case 4:
+        Operands[Operand] = Data.getULEB128(&Offset);
+        break;
+      case 3: // global as uint32
+         Operands[Operand] = Data.getU32(&Offset);
+         break;
+      default:
+        return false; // Unknown Wasm location
+      }
+      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");
+    }
+
+    OperandEndOffsets[Operand] = Offset;
+  }
+
+  EndOffset = Offset;
+  return true;
+}
+
+std::optional<unsigned> DWARFExpression::Operation::getSubCode() const {
+  if (!Desc.Op.size() || Desc.Op[0] != Operation::SizeSubOpLEB)
+    return std::nullopt;
+  return Operands[0];
+}
+
+bool DWARFExpression::operator==(const DWARFExpression &RHS) const {
+  if (AddressSize != RHS.AddressSize || Format != RHS.Format)
+    return false;
+  return Data.getData() == RHS.Data.getData();
+}
+
+void DWARFExpressionPrinter::prettyPrintBaseTypeRef(DWARFUnit *U,
+                                                    raw_ostream &OS,
+                                                    DIDumpOptions DumpOpts,
+                                                    ArrayRef<uint64_t> 
Operands,
+                                                    unsigned Operand) {
+  assert(Operand < Operands.size() && "operand out of bounds");
+  if (!U) {
+    OS << format(" <base_type ref: 0x%" PRIx64 ">", Operands[Operand]);
+    return;
+  }
+  auto Die = U->getDIEForOffset(U->getOffset() + Operands[Operand]);
+  if (Die && Die.getTag() == dwarf::DW_TAG_base_type) {
+    OS << " (";
+    if (DumpOpts.Verbose)
+      OS << format("0x%08" PRIx64 " -> ", Operands[Operand]);
+    OS << format("0x%08" PRIx64 ")", U->getOffset() + Operands[Operand]);
+    if (auto Name = dwarf::toString(Die.find(dwarf::DW_AT_name)))
+      OS << " \"" << *Name << "\"";
+  } else {
+    OS << format(" <invalid base_type ref: 0x%" PRIx64 ">", Operands[Operand]);
+  }
+}
+
+bool DWARFExpressionPrinter::prettyPrintRegisterOp(
+    DWARFUnit *U, raw_ostream &OS, DIDumpOptions DumpOpts, uint8_t Opcode,
+    ArrayRef<uint64_t> Operands) {
+  if (!DumpOpts.GetNameForDWARFReg)
+    return false;
+
+  uint64_t DwarfRegNum;
+  unsigned OpNum = 0;
+
+  if (Opcode == DW_OP_bregx || Opcode == DW_OP_regx ||
+      Opcode == DW_OP_regval_type)
+    DwarfRegNum = Operands[OpNum++];
+  else if (Opcode >= DW_OP_breg0 && Opcode < DW_OP_bregx)
+    DwarfRegNum = Opcode - DW_OP_breg0;
+  else
+    DwarfRegNum = Opcode - DW_OP_reg0;
+
+  auto RegName = DumpOpts.GetNameForDWARFReg(DwarfRegNum, DumpOpts.IsEH);
+  if (!RegName.empty()) {
+    if ((Opcode >= DW_OP_breg0 && Opcode <= DW_OP_breg31) ||
+        Opcode == DW_OP_bregx)
+      OS << ' ' << RegName << format("%+" PRId64, Operands[OpNum]);
+    else
+      OS << ' ' << RegName.data();
+
+    if (Opcode == DW_OP_regval_type)
+      prettyPrintBaseTypeRef(U, OS, DumpOpts, Operands, 1);
+    return true;
+  }
+
+  return false;
+}
+
+bool DWARFExpressionPrinter::printOp(const DWARFExpression::Operation *Op,
+                                     raw_ostream &OS, DIDumpOptions DumpOpts,
+                                     const DWARFExpression *Expr,
+                                     DWARFUnit *U) {
+  if (Op->Error) {
+    OS << "<decoding error>";
+    return false;
+  }
+
+  StringRef Name = OperationEncodingString(Op->Opcode);
+  assert(!Name.empty() && "DW_OP has no name!");
+  OS << Name;
+
+  if ((Op->Opcode >= DW_OP_breg0 && Op->Opcode <= DW_OP_breg31) ||
+      (Op->Opcode >= DW_OP_reg0 && Op->Opcode <= DW_OP_reg31) ||
+      Op->Opcode == DW_OP_bregx || Op->Opcode == DW_OP_regx ||
+      Op->Opcode == DW_OP_regval_type)
+    if (prettyPrintRegisterOp(U, OS, DumpOpts, Op->Opcode, Op->Operands))
+      return true;
+
+  for (unsigned Operand = 0; Operand < Op->Desc.Op.size(); ++Operand) {
+    unsigned Size = Op->Desc.Op[Operand];
+    unsigned Signed = Size & DWARFExpression::Operation::SignBit;
+
+    if (Size == DWARFExpression::Operation::SizeSubOpLEB) {
+      StringRef SubName =
+          SubOperationEncodingString(Op->Opcode, Op->Operands[Operand]);
+      assert(!SubName.empty() && "DW_OP SubOp has no name!");
+      OS << " " << SubName;
+    } else if (Size == DWARFExpression::Operation::BaseTypeRef && U) {
+      // For DW_OP_convert the operand may be 0 to indicate that conversion to
+      // the generic type should be done. The same holds for DW_OP_reinterpret,
+      // which is currently not supported.
+      if (Op->Opcode == DW_OP_convert && Op->Operands[Operand] == 0)
+        OS << " 0x0";
+      else
+        prettyPrintBaseTypeRef(U, OS, DumpOpts, Op->Operands, Operand);
+    } else if (Size == DWARFExpression::Operation::WasmLocationArg) {
+      assert(Operand == 1);
+      switch (Op->Operands[0]) {
+      case 0:
+      case 1:
+      case 2:
+      case 3: // global as uint32
+      case 4:
+        OS << format(" 0x%" PRIx64, Op->Operands[Operand]);
+        break;
+      default: assert(false);
+      }
+    } else if (Size == DWARFExpression::Operation::SizeBlock) {
+      uint64_t Offset = Op->Operands[Operand];
+      for (unsigned i = 0; i < Op->Operands[Operand - 1]; ++i)
+        OS << format(" 0x%02x", Expr->Data.getU8(&Offset));
+    } else {
+      if (Signed)
+        OS << format(" %+" PRId64, (int64_t)Op->Operands[Operand]);
+      else if (Op->Opcode != DW_OP_entry_value &&
+               Op->Opcode != DW_OP_GNU_entry_value)
+        OS << format(" 0x%" PRIx64, Op->Operands[Operand]);
+    }
+  }
+  return true;
+}
+
+void DWARFExpressionPrinter::print(const DWARFExpression *E, raw_ostream &OS,
+                                   DIDumpOptions DumpOpts, DWARFUnit *U,
+                                   bool IsEH) {
+  uint32_t EntryValExprSize = 0;
+  uint64_t EntryValStartOffset = 0;
+  if (E->Data.getData().empty())
+    OS << "<empty>";
+
+  for (auto &Op : *E) {
+    DumpOpts.IsEH = IsEH;
+    if (!printOp(&Op, OS, DumpOpts, E, U)) {
+      uint64_t FailOffset = Op.getEndOffset();
+      while (FailOffset < E->Data.getData().size())
+        OS << format(" %02x", E->Data.getU8(&FailOffset));
+      return;
+    }
+
+    if (Op.getCode() == DW_OP_entry_value ||
+        Op.getCode() == DW_OP_GNU_entry_value) {
+      OS << "(";
+      EntryValExprSize = Op.getRawOperand(0);
+      EntryValStartOffset = Op.getEndOffset();
+      continue;
+    }
+
+    if (EntryValExprSize) {
+      EntryValExprSize -= Op.getEndOffset() - EntryValStartOffset;
+      if (EntryValExprSize == 0)
+        OS << ")";
+    }
+
+    if (Op.getEndOffset() < E->Data.getData().size())
+      OS << ", ";
+  }
+}
+
+/// A user-facing string representation of a DWARF expression. This might be an
+/// Address expression, in which case it will be implicitly dereferenced, or a
+/// Value expression.
+struct PrintedExpr {
+  enum ExprKind {
+    Address,
+    Value,
+  };
+  ExprKind Kind;
+  SmallString<16> String;
+
+  PrintedExpr(ExprKind K = Address) : Kind(K) {}
+};
+
+static bool printCompactDWARFExpr(
+    raw_ostream &OS, DWARFExpression::iterator I,
+    const DWARFExpression::iterator E,
+    std::function<StringRef(uint64_t RegNum, bool IsEH)> GetNameForDWARFReg =
+        nullptr) {
+  SmallVector<PrintedExpr, 4> Stack;
+
+  while (I != E) {
+    const DWARFExpression::Operation &Op = *I;
+    uint8_t Opcode = Op.getCode();
+    switch (Opcode) {
+    case dwarf::DW_OP_regx: {
+      // DW_OP_regx: A register, with the register num given as an operand.
+      // Printed as the plain register name.
+      uint64_t DwarfRegNum = Op.getRawOperand(0);
+      auto RegName = GetNameForDWARFReg(DwarfRegNum, false);
+      if (RegName.empty())
+        return false;
+      raw_svector_ostream S(Stack.emplace_back(PrintedExpr::Value).String);
+      S << RegName;
+      break;
+    }
+    case dwarf::DW_OP_bregx: {
+      int DwarfRegNum = Op.getRawOperand(0);
+      int64_t Offset = Op.getRawOperand(1);
+      auto RegName = GetNameForDWARFReg(DwarfRegNum, false);
+      if (RegName.empty())
+        return false;
+      raw_svector_ostream S(Stack.emplace_back().String);
+      S << RegName;
+      if (Offset)
+        S << format("%+" PRId64, Offset);
+      break;
+    }
+    case dwarf::DW_OP_entry_value:
+    case dwarf::DW_OP_GNU_entry_value: {
+      // DW_OP_entry_value contains a sub-expression which must be rendered
+      // separately.
+      uint64_t SubExprLength = Op.getRawOperand(0);
+      DWARFExpression::iterator SubExprEnd = I.skipBytes(SubExprLength);
+      ++I;
+      raw_svector_ostream S(Stack.emplace_back().String);
+      S << "entry(";
+      printCompactDWARFExpr(S, I, SubExprEnd, GetNameForDWARFReg);
+      S << ")";
+      I = SubExprEnd;
+      continue;
+    }
+    case dwarf::DW_OP_stack_value: {
+      // The top stack entry should be treated as the actual value of tne
+      // variable, rather than the address of the variable in memory.
+      assert(!Stack.empty());
+      Stack.back().Kind = PrintedExpr::Value;
+      break;
+    }
+    case dwarf::DW_OP_nop: {
+      break;
+    }
+    case dwarf::DW_OP_LLVM_user: {
+      assert(Op.getSubCode() == dwarf::DW_OP_LLVM_nop);
+      break;
+    }
+    default:
+      if (Opcode >= dwarf::DW_OP_reg0 && Opcode <= dwarf::DW_OP_reg31) {
+        // DW_OP_reg<N>: A register, with the register num implied by the
+        // opcode. Printed as the plain register name.
+        uint64_t DwarfRegNum = Opcode - dwarf::DW_OP_reg0;
+        auto RegName = GetNameForDWARFReg(DwarfRegNum, false);
+        if (RegName.empty())
+          return false;
+        raw_svector_ostream S(Stack.emplace_back(PrintedExpr::Value).String);
+        S << RegName;
+      } else if (Opcode >= dwarf::DW_OP_breg0 &&
+                 Opcode <= dwarf::DW_OP_breg31) {
+        int DwarfRegNum = Opcode - dwarf::DW_OP_breg0;
+        int64_t Offset = Op.getRawOperand(0);
+        auto RegName = GetNameForDWARFReg(DwarfRegNum, false);
+        if (RegName.empty())
+          return false;
+        raw_svector_ostream S(Stack.emplace_back().String);
+        S << RegName;
+        if (Offset)
+          S << format("%+" PRId64, Offset);
+      } else {
+        // If we hit an unknown operand, we don't know its effect on the stack,
+        // so bail out on the whole expression.
+        OS << "<unknown op " << dwarf::OperationEncodingString(Opcode) << " ("
+           << (int)Opcode << ")>";
+        return false;
+      }
+      break;
+    }
+    ++I;
+  }
+
+  if (Stack.size() != 1) {
+    OS << "<stack of size " << Stack.size() << ", expected 1>";
+    return false;
+  }
+
+  if (Stack.front().Kind == PrintedExpr::Address)
+    OS << "[" << Stack.front().String << "]";
+  else
+    OS << Stack.front().String;
+
+  return true;
+}
+
+bool DWARFExpressionPrinter::printCompact(
+    const DWARFExpression *E, raw_ostream &OS,
+    std::function<StringRef(uint64_t RegNum, bool IsEH)> GetNameForDWARFReg) {
+  return printCompactDWARFExpr(OS, E->begin(), E->end(), GetNameForDWARFReg);
+}
+
+} // namespace llvm
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFExpressionPrinter.cpp 
b/llvm/lib/DebugInfo/DWARF/DWARFExpressionPrinter.cpp
deleted file mode 100644
index 16133b637e875..0000000000000
--- a/llvm/lib/DebugInfo/DWARF/DWARFExpressionPrinter.cpp
+++ /dev/null
@@ -1,311 +0,0 @@
-//===-- DWARFExpression.cpp 
-----------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/DebugInfo/DWARF/DWARFExpressionPrinter.h"
-#include "llvm/ADT/SmallString.h"
-#include "llvm/DebugInfo/DWARF/DWARFUnit.h"
-#include "llvm/DebugInfo/DWARF/LowLevel/DWARFExpression.h"
-#include "llvm/Support/Format.h"
-#include <cassert>
-#include <cstdint>
-#include <vector>
-
-using namespace llvm;
-using namespace dwarf;
-
-namespace llvm {
-
-typedef DWARFExpression::Operation Op;
-typedef Op::Description Desc;
-
-static void prettyPrintBaseTypeRef(DWARFUnit *U, raw_ostream &OS,
-                                   DIDumpOptions DumpOpts,
-                                   ArrayRef<uint64_t> Operands,
-                                   unsigned Operand) {
-  assert(Operand < Operands.size() && "operand out of bounds");
-  if (!U) {
-    OS << format(" <base_type ref: 0x%" PRIx64 ">", Operands[Operand]);
-    return;
-  }
-  auto Die = U->getDIEForOffset(U->getOffset() + Operands[Operand]);
-  if (Die && Die.getTag() == dwarf::DW_TAG_base_type) {
-    OS << " (";
-    if (DumpOpts.Verbose)
-      OS << format("0x%08" PRIx64 " -> ", Operands[Operand]);
-    OS << format("0x%08" PRIx64 ")", U->getOffset() + Operands[Operand]);
-    if (auto Name = dwarf::toString(Die.find(dwarf::DW_AT_name)))
-      OS << " \"" << *Name << "\"";
-  } else {
-    OS << format(" <invalid base_type ref: 0x%" PRIx64 ">", Operands[Operand]);
-  }
-}
-
-static bool printOp(const DWARFExpression::Operation *Op, raw_ostream &OS,
-                    DIDumpOptions DumpOpts, const DWARFExpression *Expr,
-                    DWARFUnit *U) {
-  if (Op->isError()) {
-    OS << "<decoding error>";
-    return false;
-  }
-
-  StringRef Name = OperationEncodingString(Op->getCode());
-  assert(!Name.empty() && "DW_OP has no name!");
-  OS << Name;
-
-  if ((Op->getCode() >= DW_OP_breg0 && Op->getCode() <= DW_OP_breg31) ||
-      (Op->getCode() >= DW_OP_reg0 && Op->getCode() <= DW_OP_reg31) ||
-      Op->getCode() == DW_OP_bregx || Op->getCode() == DW_OP_regx ||
-      Op->getCode() == DW_OP_regval_type)
-    if (prettyPrintRegisterOp(U, OS, DumpOpts, Op->getCode(),
-                              Op->getRawOperands()))
-      return true;
-
-  for (unsigned Operand = 0; Operand < Op->getDescription().Op.size();
-       ++Operand) {
-    unsigned Size = Op->getDescription().Op[Operand];
-    unsigned Signed = Size & DWARFExpression::Operation::SignBit;
-
-    if (Size == DWARFExpression::Operation::SizeSubOpLEB) {
-      StringRef SubName =
-          SubOperationEncodingString(Op->getCode(), 
Op->getRawOperand(Operand));
-      assert(!SubName.empty() && "DW_OP SubOp has no name!");
-      OS << " " << SubName;
-    } else if (Size == DWARFExpression::Operation::BaseTypeRef && U) {
-      // For DW_OP_convert the operand may be 0 to indicate that conversion to
-      // the generic type should be done. The same holds for DW_OP_reinterpret,
-      // which is currently not supported.
-      if (Op->getCode() == DW_OP_convert && Op->getRawOperand(Operand) == 0)
-        OS << " 0x0";
-      else
-        prettyPrintBaseTypeRef(U, OS, DumpOpts, Op->getRawOperands(), Operand);
-    } else if (Size == DWARFExpression::Operation::WasmLocationArg) {
-      assert(Operand == 1);
-      switch (Op->getRawOperand(0)) {
-      case 0:
-      case 1:
-      case 2:
-      case 3: // global as uint32
-      case 4:
-        OS << format(" 0x%" PRIx64, Op->getRawOperand(Operand));
-        break;
-      default:
-        assert(false);
-      }
-    } else if (Size == DWARFExpression::Operation::SizeBlock) {
-      uint64_t Offset = Op->getRawOperand(Operand);
-      for (unsigned i = 0; i < Op->getRawOperand(Operand - 1); ++i)
-        OS << format(" 0x%02x",
-                     static_cast<uint8_t>(Expr->getData()[Offset++]));
-    } else {
-      if (Signed)
-        OS << format(" %+" PRId64, (int64_t)Op->getRawOperand(Operand));
-      else if (Op->getCode() != DW_OP_entry_value &&
-               Op->getCode() != DW_OP_GNU_entry_value)
-        OS << format(" 0x%" PRIx64, Op->getRawOperand(Operand));
-    }
-  }
-  return true;
-}
-
-void printDwarfExpression(const DWARFExpression *E, raw_ostream &OS,
-                          DIDumpOptions DumpOpts, DWARFUnit *U, bool IsEH) {
-  uint32_t EntryValExprSize = 0;
-  uint64_t EntryValStartOffset = 0;
-  if (E->getData().empty())
-    OS << "<empty>";
-
-  for (auto &Op : *E) {
-    DumpOpts.IsEH = IsEH;
-    if (!printOp(&Op, OS, DumpOpts, E, U)) {
-      uint64_t FailOffset = Op.getEndOffset();
-      while (FailOffset < E->getData().size())
-        OS << format(" %02x", 
static_cast<uint8_t>(E->getData()[FailOffset++]));
-      return;
-    }
-
-    if (Op.getCode() == DW_OP_entry_value ||
-        Op.getCode() == DW_OP_GNU_entry_value) {
-      OS << "(";
-      EntryValExprSize = Op.getRawOperand(0);
-      EntryValStartOffset = Op.getEndOffset();
-      continue;
-    }
-
-    if (EntryValExprSize) {
-      EntryValExprSize -= Op.getEndOffset() - EntryValStartOffset;
-      if (EntryValExprSize == 0)
-        OS << ")";
-    }
-
-    if (Op.getEndOffset() < E->getData().size())
-      OS << ", ";
-  }
-}
-
-/// A user-facing string representation of a DWARF expression. This might be an
-/// Address expression, in which case it will be implicitly dereferenced, or a
-/// Value expression.
-struct PrintedExpr {
-  enum ExprKind {
-    Address,
-    Value,
-  };
-  ExprKind Kind;
-  SmallString<16> String;
-
-  PrintedExpr(ExprKind K = Address) : Kind(K) {}
-};
-
-static bool printCompactDWARFExpr(
-    raw_ostream &OS, DWARFExpression::iterator I,
-    const DWARFExpression::iterator E,
-    std::function<StringRef(uint64_t RegNum, bool IsEH)> GetNameForDWARFReg =
-        nullptr) {
-  SmallVector<PrintedExpr, 4> Stack;
-
-  while (I != E) {
-    const DWARFExpression::Operation &Op = *I;
-    uint8_t Opcode = Op.getCode();
-    switch (Opcode) {
-    case dwarf::DW_OP_regx: {
-      // DW_OP_regx: A register, with the register num given as an operand.
-      // Printed as the plain register name.
-      uint64_t DwarfRegNum = Op.getRawOperand(0);
-      auto RegName = GetNameForDWARFReg(DwarfRegNum, false);
-      if (RegName.empty())
-        return false;
-      raw_svector_ostream S(Stack.emplace_back(PrintedExpr::Value).String);
-      S << RegName;
-      break;
-    }
-    case dwarf::DW_OP_bregx: {
-      int DwarfRegNum = Op.getRawOperand(0);
-      int64_t Offset = Op.getRawOperand(1);
-      auto RegName = GetNameForDWARFReg(DwarfRegNum, false);
-      if (RegName.empty())
-        return false;
-      raw_svector_ostream S(Stack.emplace_back().String);
-      S << RegName;
-      if (Offset)
-        S << format("%+" PRId64, Offset);
-      break;
-    }
-    case dwarf::DW_OP_entry_value:
-    case dwarf::DW_OP_GNU_entry_value: {
-      // DW_OP_entry_value contains a sub-expression which must be rendered
-      // separately.
-      uint64_t SubExprLength = Op.getRawOperand(0);
-      DWARFExpression::iterator SubExprEnd = I.skipBytes(SubExprLength);
-      ++I;
-      raw_svector_ostream S(Stack.emplace_back().String);
-      S << "entry(";
-      printCompactDWARFExpr(S, I, SubExprEnd, GetNameForDWARFReg);
-      S << ")";
-      I = SubExprEnd;
-      continue;
-    }
-    case dwarf::DW_OP_stack_value: {
-      // The top stack entry should be treated as the actual value of tne
-      // variable, rather than the address of the variable in memory.
-      assert(!Stack.empty());
-      Stack.back().Kind = PrintedExpr::Value;
-      break;
-    }
-    case dwarf::DW_OP_nop: {
-      break;
-    }
-    case dwarf::DW_OP_LLVM_user: {
-      assert(Op.getSubCode() == dwarf::DW_OP_LLVM_nop);
-      break;
-    }
-    default:
-      if (Opcode >= dwarf::DW_OP_reg0 && Opcode <= dwarf::DW_OP_reg31) {
-        // DW_OP_reg<N>: A register, with the register num implied by the
-        // opcode. Printed as the plain register name.
-        uint64_t DwarfRegNum = Opcode - dwarf::DW_OP_reg0;
-        auto RegName = GetNameForDWARFReg(DwarfRegNum, false);
-        if (RegName.empty())
-          return false;
-        raw_svector_ostream S(Stack.emplace_back(PrintedExpr::Value).String);
-        S << RegName;
-      } else if (Opcode >= dwarf::DW_OP_breg0 &&
-                 Opcode <= dwarf::DW_OP_breg31) {
-        int DwarfRegNum = Opcode - dwarf::DW_OP_breg0;
-        int64_t Offset = Op.getRawOperand(0);
-        auto RegName = GetNameForDWARFReg(DwarfRegNum, false);
-        if (RegName.empty())
-          return false;
-        raw_svector_ostream S(Stack.emplace_back().String);
-        S << RegName;
-        if (Offset)
-          S << format("%+" PRId64, Offset);
-      } else {
-        // If we hit an unknown operand, we don't know its effect on the stack,
-        // so bail out on the whole expression.
-        OS << "<unknown op " << dwarf::OperationEncodingString(Opcode) << " ("
-           << (int)Opcode << ")>";
-        return false;
-      }
-      break;
-    }
-    ++I;
-  }
-
-  if (Stack.size() != 1) {
-    OS << "<stack of size " << Stack.size() << ", expected 1>";
-    return false;
-  }
-
-  if (Stack.front().Kind == PrintedExpr::Address)
-    OS << "[" << Stack.front().String << "]";
-  else
-    OS << Stack.front().String;
-
-  return true;
-}
-
-bool printDwarfExpressionCompact(
-    const DWARFExpression *E, raw_ostream &OS,
-    std::function<StringRef(uint64_t RegNum, bool IsEH)> GetNameForDWARFReg) {
-  return printCompactDWARFExpr(OS, E->begin(), E->end(), GetNameForDWARFReg);
-}
-
-bool prettyPrintRegisterOp(DWARFUnit *U, raw_ostream &OS,
-                           DIDumpOptions DumpOpts, uint8_t Opcode,
-                           ArrayRef<uint64_t> Operands) {
-  if (!DumpOpts.GetNameForDWARFReg)
-    return false;
-
-  uint64_t DwarfRegNum;
-  unsigned OpNum = 0;
-
-  if (Opcode == DW_OP_bregx || Opcode == DW_OP_regx ||
-      Opcode == DW_OP_regval_type)
-    DwarfRegNum = Operands[OpNum++];
-  else if (Opcode >= DW_OP_breg0 && Opcode < DW_OP_bregx)
-    DwarfRegNum = Opcode - DW_OP_breg0;
-  else
-    DwarfRegNum = Opcode - DW_OP_reg0;
-
-  auto RegName = DumpOpts.GetNameForDWARFReg(DwarfRegNum, DumpOpts.IsEH);
-  if (!RegName.empty()) {
-    if ((Opcode >= DW_OP_breg0 && Opcode <= DW_OP_breg31) ||
-        Opcode == DW_OP_bregx)
-      OS << ' ' << RegName << format("%+" PRId64, Operands[OpNum]);
-    else
-      OS << ' ' << RegName.data();
-
-    if (Opcode == DW_OP_regval_type)
-      prettyPrintBaseTypeRef(U, OS, DumpOpts, Operands, 1);
-    return true;
-  }
-
-  return false;
-}
-
-} // namespace llvm
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp 
b/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp
index ef59c82fc6a01..d719a47c84072 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp
@@ -19,12 +19,12 @@
 #include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h"
 #include "llvm/DebugInfo/DWARF/DWARFDebugRnglists.h"
 #include "llvm/DebugInfo/DWARF/DWARFDie.h"
+#include "llvm/DebugInfo/DWARF/DWARFExpression.h"
 #include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
 #include "llvm/DebugInfo/DWARF/DWARFListTable.h"
 #include "llvm/DebugInfo/DWARF/DWARFObject.h"
 #include "llvm/DebugInfo/DWARF/DWARFSection.h"
 #include "llvm/DebugInfo/DWARF/DWARFTypeUnit.h"
-#include "llvm/DebugInfo/DWARF/LowLevel/DWARFExpression.h"
 #include "llvm/Object/ObjectFile.h"
 #include "llvm/Support/DataExtractor.h"
 #include "llvm/Support/Errc.h"
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp 
b/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp
index 8ec3f1729b974..c12786cac8686 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp
@@ -19,13 +19,13 @@
 #include "llvm/DebugInfo/DWARF/DWARFDebugLine.h"
 #include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h"
 #include "llvm/DebugInfo/DWARF/DWARFDie.h"
+#include "llvm/DebugInfo/DWARF/DWARFExpression.h"
 #include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
 #include "llvm/DebugInfo/DWARF/DWARFLocationExpression.h"
 #include "llvm/DebugInfo/DWARF/DWARFObject.h"
 #include "llvm/DebugInfo/DWARF/DWARFSection.h"
 #include "llvm/DebugInfo/DWARF/DWARFTypeUnit.h"
 #include "llvm/DebugInfo/DWARF/DWARFUnit.h"
-#include "llvm/DebugInfo/DWARF/LowLevel/DWARFExpression.h"
 #include "llvm/Object/Error.h"
 #include "llvm/Support/DJB.h"
 #include "llvm/Support/Error.h"
diff --git a/llvm/lib/DebugInfo/DWARF/LowLevel/CMakeLists.txt 
b/llvm/lib/DebugInfo/DWARF/LowLevel/CMakeLists.txt
deleted file mode 100644
index c11a2589a552d..0000000000000
--- a/llvm/lib/DebugInfo/DWARF/LowLevel/CMakeLists.txt
+++ /dev/null
@@ -1,14 +0,0 @@
-add_llvm_component_library(LLVMDebugInfoDWARFLowLevel
-  DWARFCFIProgram.cpp
-  DWARFExpression.cpp
-
-  ADDITIONAL_HEADER_DIRS
-  ${LLVM_MAIN_INCLUDE_DIR}/llvm/DebugInfo/DWARF/LowLevel
-
-  // This code should have almost no dependencies. Anything that needs
-  // more should use the higher-level DebugInfo/DWARF/ library.
-  LINK_COMPONENTS
-  BinaryFormat
-  Support
-  TargetParser
-  )
diff --git a/llvm/lib/DebugInfo/DWARF/LowLevel/DWARFExpression.cpp 
b/llvm/lib/DebugInfo/DWARF/LowLevel/DWARFExpression.cpp
deleted file mode 100644
index 70724185463b0..0000000000000
--- a/llvm/lib/DebugInfo/DWARF/LowLevel/DWARFExpression.cpp
+++ /dev/null
@@ -1,253 +0,0 @@
-//===-- DWARFExpression.cpp 
-----------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/DebugInfo/DWARF/LowLevel/DWARFExpression.h"
-#include "llvm/ADT/SmallString.h"
-#include "llvm/Support/Format.h"
-#include <cassert>
-#include <cstdint>
-#include <vector>
-
-using namespace llvm;
-using namespace dwarf;
-
-namespace llvm {
-
-typedef DWARFExpression::Operation Op;
-typedef Op::Description Desc;
-
-static std::vector<Desc> getOpDescriptions() {
-  std::vector<Desc> Descriptions;
-  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_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);
-  Descriptions[DW_OP_skip] = Desc(Op::Dwarf2, Op::SignedSize2);
-  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::Dwarf4, Op::SizeLEB, Op::SizeBlock);
-  Descriptions[DW_OP_stack_value] = Desc(Op::Dwarf4);
-  Descriptions[DW_OP_implicit_pointer] =
-      Desc(Op::Dwarf5, Op::SizeRefAddr, Op::SignedSizeLEB);
-  Descriptions[DW_OP_addrx] = Desc(Op::Dwarf5, Op::SizeLEB);
-  Descriptions[DW_OP_constx] = Desc(Op::Dwarf5, Op::SizeLEB);
-  Descriptions[DW_OP_entry_value] = Desc(Op::Dwarf5, Op::SizeLEB);
-  Descriptions[DW_OP_convert] = Desc(Op::Dwarf5, Op::BaseTypeRef);
-  Descriptions[DW_OP_regval_type] =
-      Desc(Op::Dwarf5, Op::SizeLEB, Op::BaseTypeRef);
-  Descriptions[DW_OP_WASM_location] =
-      Desc(Op::Dwarf4, Op::SizeLEB, Op::WasmLocationArg);
-  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);
-  Descriptions[DW_OP_GNU_entry_value] = Desc(Op::Dwarf4, Op::SizeLEB);
-  Descriptions[DW_OP_GNU_implicit_pointer] =
-      Desc(Op::Dwarf4, Op::SizeRefAddr, Op::SignedSizeLEB);
-  // This Description acts as a marker that getSubOpDesc must be called
-  // to fetch the final Description for the operation. Each such final
-  // Description must share the same first SizeSubOpLEB operand.
-  Descriptions[DW_OP_LLVM_user] = Desc(Op::Dwarf5, Op::SizeSubOpLEB);
-  return Descriptions;
-}
-
-static Desc getDescImpl(ArrayRef<Desc> Descriptions, unsigned Opcode) {
-  // Handle possible corrupted or unsupported operation.
-  if (Opcode >= Descriptions.size())
-    return {};
-  return Descriptions[Opcode];
-}
-
-static Desc getOpDesc(unsigned Opcode) {
-  static std::vector<Desc> Descriptions = getOpDescriptions();
-  return getDescImpl(Descriptions, Opcode);
-}
-
-static std::vector<Desc> getSubOpDescriptions() {
-  static constexpr unsigned LlvmUserDescriptionsSize = 1
-#define HANDLE_DW_OP_LLVM_USEROP(ID, NAME) +1
-#include "llvm/BinaryFormat/Dwarf.def"
-      ;
-  std::vector<Desc> Descriptions;
-  Descriptions.resize(LlvmUserDescriptionsSize);
-  Descriptions[DW_OP_LLVM_nop] = Desc(Op::Dwarf5, Op::SizeSubOpLEB);
-  return Descriptions;
-}
-
-static Desc getSubOpDesc(unsigned Opcode, unsigned SubOpcode) {
-  assert(Opcode == DW_OP_LLVM_user);
-  static std::vector<Desc> Descriptions = getSubOpDescriptions();
-  return getDescImpl(Descriptions, SubOpcode);
-}
-
-bool DWARFExpression::Operation::extract(DataExtractor Data,
-                                         uint8_t AddressSize, uint64_t Offset,
-                                         std::optional<DwarfFormat> Format) {
-  EndOffset = Offset;
-  Opcode = Data.getU8(&Offset);
-
-  Desc = getOpDesc(Opcode);
-  if (Desc.Version == Operation::DwarfNA)
-    return false;
-
-  Operands.resize(Desc.Op.size());
-  OperandEndOffsets.resize(Desc.Op.size());
-  for (unsigned Operand = 0; Operand < Desc.Op.size(); ++Operand) {
-    unsigned Size = Desc.Op[Operand];
-    unsigned Signed = Size & Operation::SignBit;
-
-    switch (Size & ~Operation::SignBit) {
-    case Operation::SizeSubOpLEB:
-      assert(Operand == 0 && "SubOp operand must be the first operand");
-      Operands[Operand] = Data.getULEB128(&Offset);
-      Desc = getSubOpDesc(Opcode, Operands[Operand]);
-      if (Desc.Version == Operation::DwarfNA)
-        return false;
-      assert(Desc.Op[Operand] == Operation::SizeSubOpLEB &&
-             "SizeSubOpLEB Description must begin with SizeSubOpLEB operand");
-      break;
-    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:
-      Operands[Operand] = Data.getUnsigned(&Offset, AddressSize);
-      break;
-    case Operation::SizeRefAddr:
-      if (!Format)
-        return false;
-      Operands[Operand] =
-          Data.getUnsigned(&Offset, dwarf::getDwarfOffsetByteSize(*Format));
-      break;
-    case Operation::SizeLEB:
-      if (Signed)
-        Operands[Operand] = Data.getSLEB128(&Offset);
-      else
-        Operands[Operand] = Data.getULEB128(&Offset);
-      break;
-    case Operation::BaseTypeRef:
-      Operands[Operand] = Data.getULEB128(&Offset);
-      break;
-    case Operation::WasmLocationArg:
-      assert(Operand == 1);
-      switch (Operands[0]) {
-      case 0:
-      case 1:
-      case 2:
-      case 4:
-        Operands[Operand] = Data.getULEB128(&Offset);
-        break;
-      case 3: // global as uint32
-        Operands[Operand] = Data.getU32(&Offset);
-        break;
-      default:
-        return false; // Unknown Wasm location
-      }
-      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");
-    }
-
-    OperandEndOffsets[Operand] = Offset;
-  }
-
-  EndOffset = Offset;
-  return true;
-}
-
-std::optional<unsigned> DWARFExpression::Operation::getSubCode() const {
-  if (!Desc.Op.size() || Desc.Op[0] != Operation::SizeSubOpLEB)
-    return std::nullopt;
-  return Operands[0];
-}
-
-bool DWARFExpression::operator==(const DWARFExpression &RHS) const {
-  if (AddressSize != RHS.AddressSize || Format != RHS.Format)
-    return false;
-  return Data.getData() == RHS.Data.getData();
-}
-
-} // namespace llvm
diff --git a/llvm/lib/DebugInfo/LogicalView/Readers/LVDWARFReader.cpp 
b/llvm/lib/DebugInfo/LogicalView/Readers/LVDWARFReader.cpp
index 696e2bc948a2e..95b7007d119bc 100644
--- a/llvm/lib/DebugInfo/LogicalView/Readers/LVDWARFReader.cpp
+++ b/llvm/lib/DebugInfo/LogicalView/Readers/LVDWARFReader.cpp
@@ -14,8 +14,7 @@
 #include "llvm/DebugInfo/LogicalView/Readers/LVDWARFReader.h"
 #include "llvm/DebugInfo/DIContext.h"
 #include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h"
-#include "llvm/DebugInfo/DWARF/DWARFExpressionPrinter.h"
-#include "llvm/DebugInfo/DWARF/LowLevel/DWARFExpression.h"
+#include "llvm/DebugInfo/DWARF/DWARFExpression.h"
 #include "llvm/DebugInfo/LogicalView/Core/LVLine.h"
 #include "llvm/DebugInfo/LogicalView/Core/LVScope.h"
 #include "llvm/DebugInfo/LogicalView/Core/LVSymbol.h"
@@ -595,7 +594,8 @@ std::string LVDWARFReader::getRegisterName(LVSmall Opcode,
     return {};
   };
   DumpOpts.GetNameForDWARFReg = GetRegName;
-  prettyPrintRegisterOp(/*U=*/nullptr, Stream, DumpOpts, Opcode, Operands);
+  DWARFExpressionPrinter::prettyPrintRegisterOp(/*U=*/nullptr, Stream, 
DumpOpts,
+                                                Opcode, Operands);
   return Stream.str();
 }
 
diff --git a/llvm/lib/ProfileData/CMakeLists.txt 
b/llvm/lib/ProfileData/CMakeLists.txt
index c2366dc0ae03e..d26af1c3d5547 100644
--- a/llvm/lib/ProfileData/CMakeLists.txt
+++ b/llvm/lib/ProfileData/CMakeLists.txt
@@ -35,7 +35,6 @@ add_llvm_component_library(LLVMProfileData
   Demangle
   Symbolize
   DebugInfoDWARF
-  DebugInfoDWARFLowLevel
   TargetParser
   )
 
diff --git a/llvm/lib/ProfileData/InstrProfCorrelator.cpp 
b/llvm/lib/ProfileData/InstrProfCorrelator.cpp
index 07b69e9fad3ec..d92107f93dc56 100644
--- a/llvm/lib/ProfileData/InstrProfCorrelator.cpp
+++ b/llvm/lib/ProfileData/InstrProfCorrelator.cpp
@@ -10,10 +10,10 @@
 #include "llvm/DebugInfo/DIContext.h"
 #include "llvm/DebugInfo/DWARF/DWARFContext.h"
 #include "llvm/DebugInfo/DWARF/DWARFDie.h"
+#include "llvm/DebugInfo/DWARF/DWARFExpression.h"
 #include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
 #include "llvm/DebugInfo/DWARF/DWARFLocationExpression.h"
 #include "llvm/DebugInfo/DWARF/DWARFUnit.h"
-#include "llvm/DebugInfo/DWARF/LowLevel/DWARFExpression.h"
 #include "llvm/Object/MachO.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/Format.h"
diff --git a/llvm/tools/dsymutil/CMakeLists.txt 
b/llvm/tools/dsymutil/CMakeLists.txt
index d3cdbe466de08..366b63b2a8695 100644
--- a/llvm/tools/dsymutil/CMakeLists.txt
+++ b/llvm/tools/dsymutil/CMakeLists.txt
@@ -15,7 +15,6 @@ set(LLVM_LINK_COMPONENTS
   DWARFLinkerClassic
   DWARFLinkerParallel
   DebugInfoDWARF
-  DebugInfoDWARFLowLevel
   MC
   Object
   Option
diff --git a/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp 
b/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp
index 138c5d0a513ed..e88e076dca996 100644
--- a/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp
+++ b/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp
@@ -39,10 +39,10 @@
 #include "llvm/DebugInfo/DWARF/DWARFDebugLine.h"
 #include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h"
 #include "llvm/DebugInfo/DWARF/DWARFDie.h"
+#include "llvm/DebugInfo/DWARF/DWARFExpression.h"
 #include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
 #include "llvm/DebugInfo/DWARF/DWARFSection.h"
 #include "llvm/DebugInfo/DWARF/DWARFUnit.h"
-#include "llvm/DebugInfo/DWARF/LowLevel/DWARFExpression.h"
 #include "llvm/MC/MCAsmBackend.h"
 #include "llvm/MC/MCAsmInfo.h"
 #include "llvm/MC/MCCodeEmitter.h"
diff --git a/llvm/tools/llvm-dwarfdump/CMakeLists.txt 
b/llvm/tools/llvm-dwarfdump/CMakeLists.txt
index aeb1b8f14d830..7c68aaac05d98 100644
--- a/llvm/tools/llvm-dwarfdump/CMakeLists.txt
+++ b/llvm/tools/llvm-dwarfdump/CMakeLists.txt
@@ -1,6 +1,5 @@
 set(LLVM_LINK_COMPONENTS
   DebugInfoDWARF
-  DebugInfoDWARFLowLevel
   AllTargetsDescs
   AllTargetsInfos
   MC
diff --git a/llvm/tools/llvm-dwarfdump/Statistics.cpp 
b/llvm/tools/llvm-dwarfdump/Statistics.cpp
index f92b2b55fa8dc..af9a93ad35b9c 100644
--- a/llvm/tools/llvm-dwarfdump/Statistics.cpp
+++ b/llvm/tools/llvm-dwarfdump/Statistics.cpp
@@ -12,7 +12,7 @@
 #include "llvm/ADT/StringSet.h"
 #include "llvm/DebugInfo/DWARF/DWARFContext.h"
 #include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h"
-#include "llvm/DebugInfo/DWARF/LowLevel/DWARFExpression.h"
+#include "llvm/DebugInfo/DWARF/DWARFExpression.h"
 #include "llvm/Object/ObjectFile.h"
 #include "llvm/Support/JSON.h"
 
diff --git a/llvm/tools/llvm-dwarfutil/CMakeLists.txt 
b/llvm/tools/llvm-dwarfutil/CMakeLists.txt
index 88335928b68dd..23a526782dd7b 100644
--- a/llvm/tools/llvm-dwarfutil/CMakeLists.txt
+++ b/llvm/tools/llvm-dwarfutil/CMakeLists.txt
@@ -11,7 +11,6 @@ set(LLVM_LINK_COMPONENTS
   DWARFLinkerClassic
   DWARFLinkerParallel
   DebugInfoDWARF
-  DebugInfoDWARFLowLevel
   MC
   ObjCopy
   Object
diff --git a/llvm/tools/llvm-dwarfutil/DebugInfoLinker.cpp 
b/llvm/tools/llvm-dwarfutil/DebugInfoLinker.cpp
index ccc1324bc66d7..285dcf75ecd9d 100644
--- a/llvm/tools/llvm-dwarfutil/DebugInfoLinker.cpp
+++ b/llvm/tools/llvm-dwarfutil/DebugInfoLinker.cpp
@@ -13,7 +13,7 @@
 #include "llvm/DWARFLinker/Classic/DWARFStreamer.h"
 #include "llvm/DWARFLinker/Parallel/DWARFLinker.h"
 #include "llvm/DebugInfo/DWARF/DWARFContext.h"
-#include "llvm/DebugInfo/DWARF/LowLevel/DWARFExpression.h"
+#include "llvm/DebugInfo/DWARF/DWARFExpression.h"
 #include "llvm/Object/ObjectFile.h"
 #include <memory>
 #include <vector>
diff --git a/llvm/tools/llvm-objdump/CMakeLists.txt 
b/llvm/tools/llvm-objdump/CMakeLists.txt
index 7e3197f0a0bd3..0306736388979 100644
--- a/llvm/tools/llvm-objdump/CMakeLists.txt
+++ b/llvm/tools/llvm-objdump/CMakeLists.txt
@@ -5,7 +5,6 @@ set(LLVM_LINK_COMPONENTS
   BinaryFormat
   DebugInfoBTF
   DebugInfoDWARF
-  DebugInfoDWARFLowLevel
   Demangle
   MC
   MCDisassembler
diff --git a/llvm/tools/llvm-objdump/SourcePrinter.cpp 
b/llvm/tools/llvm-objdump/SourcePrinter.cpp
index 3630502172977..bf3363795a4d9 100644
--- a/llvm/tools/llvm-objdump/SourcePrinter.cpp
+++ b/llvm/tools/llvm-objdump/SourcePrinter.cpp
@@ -15,8 +15,7 @@
 #include "SourcePrinter.h"
 #include "llvm-objdump.h"
 #include "llvm/ADT/SmallSet.h"
-#include "llvm/DebugInfo/DWARF/DWARFExpressionPrinter.h"
-#include "llvm/DebugInfo/DWARF/LowLevel/DWARFExpression.h"
+#include "llvm/DebugInfo/DWARF/DWARFExpression.h"
 #include "llvm/Support/FormatVariadic.h"
 
 #define DEBUG_TYPE "objdump"
@@ -46,7 +45,7 @@ void LiveVariable::print(raw_ostream &OS, const 
MCRegisterInfo &MRI) const {
     return {};
   };
 
-  printDwarfExpressionCompact(&Expression, OS, GetRegName);
+  DWARFExpressionPrinter::printCompact(&Expression, OS, GetRegName);
 }
 
 void LiveVariablePrinter::addVariable(DWARFDie FuncDie, DWARFDie VarDie) {
diff --git a/llvm/unittests/DebugInfo/DWARF/CMakeLists.txt 
b/llvm/unittests/DebugInfo/DWARF/CMakeLists.txt
index dc8240f904b4c..0c5b3f28ca3d5 100644
--- a/llvm/unittests/DebugInfo/DWARF/CMakeLists.txt
+++ b/llvm/unittests/DebugInfo/DWARF/CMakeLists.txt
@@ -4,7 +4,6 @@ set(LLVM_LINK_COMPONENTS
   BinaryFormat
   CodeGenTypes
   DebugInfoDWARF
-  DebugInfoDWARFLowLevel
   MC
   Object
   ObjectYAML
diff --git 
a/llvm/unittests/DebugInfo/DWARF/DWARFExpressionCompactPrinterTest.cpp 
b/llvm/unittests/DebugInfo/DWARF/DWARFExpressionCompactPrinterTest.cpp
index 3e0cc8fed84c0..9225ab0125f2f 100644
--- a/llvm/unittests/DebugInfo/DWARF/DWARFExpressionCompactPrinterTest.cpp
+++ b/llvm/unittests/DebugInfo/DWARF/DWARFExpressionCompactPrinterTest.cpp
@@ -10,8 +10,7 @@
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/DebugInfo/DWARF/DWARFContext.h"
 #include "llvm/DebugInfo/DWARF/DWARFDie.h"
-#include "llvm/DebugInfo/DWARF/DWARFExpressionPrinter.h"
-#include "llvm/DebugInfo/DWARF/LowLevel/DWARFExpression.h"
+#include "llvm/DebugInfo/DWARF/DWARFExpression.h"
 #include "llvm/MC/MCInstrInfo.h"
 #include "llvm/MC/MCRegisterInfo.h"
 #include "llvm/MC/TargetRegistry.h"
@@ -71,7 +70,7 @@ void DWARFExpressionCompactPrinterTest::TestExprPrinter(
     return {};
   };
 
-  printDwarfExpressionCompact(&Expr, OS, GetRegName);
+  DWARFExpressionPrinter::printCompact(&Expr, OS, GetRegName);
   EXPECT_EQ(OS.str(), Expected);
 }
 
diff --git a/llvm/unittests/DebugInfo/DWARF/DWARFExpressionCopyBytesTest.cpp 
b/llvm/unittests/DebugInfo/DWARF/DWARFExpressionCopyBytesTest.cpp
index 78d383ed0b22e..ec9c0dddcbc0c 100644
--- a/llvm/unittests/DebugInfo/DWARF/DWARFExpressionCopyBytesTest.cpp
+++ b/llvm/unittests/DebugInfo/DWARF/DWARFExpressionCopyBytesTest.cpp
@@ -11,7 +11,7 @@
 #include "llvm/DebugInfo/DWARF/DWARFContext.h"
 #include "llvm/DebugInfo/DWARF/DWARFDebugFrame.h"
 #include "llvm/DebugInfo/DWARF/DWARFDie.h"
-#include "llvm/DebugInfo/DWARF/LowLevel/DWARFExpression.h"
+#include "llvm/DebugInfo/DWARF/DWARFExpression.h"
 #include "llvm/MC/MCAsmBackend.h"
 #include "llvm/MC/MCAsmInfo.h"
 #include "llvm/MC/MCCodeEmitter.h"
diff --git a/utils/bazel/llvm-project-overlay/bolt/BUILD.bazel 
b/utils/bazel/llvm-project-overlay/bolt/BUILD.bazel
index 97c25bcdece7b..b5cd6dbcbd4f9 100644
--- a/utils/bazel/llvm-project-overlay/bolt/BUILD.bazel
+++ b/utils/bazel/llvm-project-overlay/bolt/BUILD.bazel
@@ -106,7 +106,6 @@ cc_library(
         "//llvm:DWARFLinker",
         "//llvm:DWP",
         "//llvm:DebugInfoDWARF",
-        "//llvm:DebugInfoDWARFLowLevel",
         "//llvm:Demangle",
         "//llvm:JITLink",
         "//llvm:MC",
@@ -297,7 +296,6 @@ cc_library(
         "//llvm:BinaryFormat",
         "//llvm:CodeGen",
         "//llvm:DebugInfoDWARF",
-        "//llvm:DebugInfoDWARFLowLevel",
         "//llvm:Demangle",
         "//llvm:ExecutionEngine",
         "//llvm:MC",
diff --git a/utils/bazel/llvm-project-overlay/llvm/BUILD.bazel 
b/utils/bazel/llvm-project-overlay/llvm/BUILD.bazel
index c28d637cea656..d5a7fdb747f86 100644
--- a/utils/bazel/llvm-project-overlay/llvm/BUILD.bazel
+++ b/utils/bazel/llvm-project-overlay/llvm/BUILD.bazel
@@ -493,7 +493,6 @@ cc_library(
         ":DebugInfo",
         ":DebugInfoCodeView",
         ":DebugInfoDWARF",
-        ":DebugInfoDWARFLowLevel",
         ":DebugInfoPDB",
         ":Demangle",
         ":MC",
@@ -573,7 +572,6 @@ cc_library(
     deps = [
         ":BinaryFormat",
         ":DebugInfo",
-        ":DebugInfoDWARFLowLevel",
         ":MC",
         ":Object",
         ":Support",
@@ -581,20 +579,6 @@ cc_library(
     ],
 )
 
-cc_library(
-    name = "DebugInfoDWARFLowLevel",
-    srcs = glob([
-        "lib/DebugInfo/DWARF/LowLevel/*.cpp",
-    ]),
-    hdrs = glob(["include/llvm/DebugInfo/DWARF/LowLevel/*.h"]),
-    copts = llvm_copts,
-    deps = [
-        ":BinaryFormat",
-        ":Support",
-        ":TargetParser",
-    ],
-)
-
 cc_library(
     name = "DebugInfoGSYM",
     srcs = glob([
@@ -1170,7 +1154,6 @@ cc_library(
         ":Core",
         ":DebugInfo",
         ":DebugInfoDWARF",
-        ":DebugInfoDWARFLowLevel",
         ":Demangle",
         ":Object",
         ":Support",
@@ -2098,7 +2081,6 @@ cc_library(
         ":Core",
         ":DebugInfoCodeView",
         ":DebugInfoDWARF",
-        ":DebugInfoDWARFLowLevel",
         ":IPO",
         ":IRPrinter",
         ":Instrumentation",
@@ -3240,7 +3222,6 @@ cc_library(
         ":CodeGenTypes",
         ":DWARFLinkerBase",
         ":DebugInfoDWARF",
-        ":DebugInfoDWARFLowLevel",
         ":MC",
         ":Support",
         ":Target",
@@ -3259,7 +3240,6 @@ cc_library(
         ":BinaryFormat",
         ":CodeGen",
         ":DebugInfoDWARF",
-        ":DebugInfoDWARFLowLevel",
         ":Support",
         ":Target",
     ],
@@ -3560,7 +3540,6 @@ cc_library(
         ":DWARFLinkerParallel",
         ":DebugInfo",
         ":DebugInfoDWARF",
-        ":DebugInfoDWARFLowLevel",
         ":DsymutilTableGen",
         ":MC",
         ":Object",
@@ -3978,7 +3957,6 @@ cc_binary(
         ":BinaryFormat",
         ":DebugInfo",
         ":DebugInfoDWARF",
-        ":DebugInfoDWARFLowLevel",
         ":MC",
         ":Object",
         ":Support",
@@ -4010,7 +3988,6 @@ cc_binary(
         ":DWARFLinker",
         ":DWARFLinkerParallel",
         ":DebugInfoDWARF",
-        ":DebugInfoDWARFLowLevel",
         ":DwarfutilOptionsTableGen",
         ":MC",
         ":ObjCopy",
@@ -4628,7 +4605,6 @@ cc_library(
         ":DebugInfo",
         ":DebugInfoBTF",
         ":DebugInfoDWARF",
-        ":DebugInfoDWARFLowLevel",
         ":Debuginfod",
         ":Demangle",
         ":MC",

_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to