leonid.mashinskiy updated this revision to Diff 181792.
leonid.mashinskiy set the repository for this revision to rLLDB LLDB.
leonid.mashinskiy added a comment.
Herald added a subscriber: arphaman.

- Ported implementation to NativePDB plugin.
- Implemented GetVariableLocationInfo for local variables of 
S_DEFRANGE_FRAMEPOINTER_REL and S_DEFRANGE_REGISTER_REL type


Repository:
  rLLDB LLDB

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D55122/new/

https://reviews.llvm.org/D55122

Files:
  lit/SymbolFile/PDB/Inputs/VariablesLocationsTest.cpp
  lit/SymbolFile/PDB/Inputs/VariablesLocationsTest.script
  lit/SymbolFile/PDB/variables-locations.test
  source/Expression/DWARFExpression.cpp
  source/Plugins/SymbolFile/NativePDB/CMakeLists.txt
  source/Plugins/SymbolFile/NativePDB/CodeViewRegisterMapping.cpp
  source/Plugins/SymbolFile/NativePDB/CodeViewRegisterMapping.h
  source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.cpp
  source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.h
  source/Plugins/SymbolFile/NativePDB/PdbFPOProgramToDWARFExpression.cpp
  source/Plugins/SymbolFile/NativePDB/PdbFPOProgramToDWARFExpression.h
  source/Plugins/SymbolFile/NativePDB/PdbIndex.h
  source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp
  source/Plugins/SymbolFile/NativePDB/PdbUtil.h
  source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
  source/Plugins/SymbolFile/PDB/CMakeLists.txt
  source/Plugins/SymbolFile/PDB/PDBLocationToDWARFExpression.cpp
  source/Plugins/SymbolFile/PDB/PDBLocationToDWARFExpression.h
  source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp
  unittests/SymbolFile/CMakeLists.txt
  unittests/SymbolFile/NativePDB/CMakeLists.txt
  unittests/SymbolFile/NativePDB/PdbFPOProgramToDWARFExpressionTests.cpp

Index: unittests/SymbolFile/NativePDB/PdbFPOProgramToDWARFExpressionTests.cpp
===================================================================
--- /dev/null
+++ unittests/SymbolFile/NativePDB/PdbFPOProgramToDWARFExpressionTests.cpp
@@ -0,0 +1,165 @@
+//===-- PDBFPOProgramToDWARFExpressionTests.cpp -----------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "gtest/gtest.h"
+
+#include "Plugins/SymbolFile/NativePDB/PdbFPOProgramToDWARFExpression.h"
+
+#include "lldb/Core/StreamBuffer.h"
+#include "lldb/Expression/DWARFExpression.h"
+#include "lldb/Utility/ArchSpec.h"
+#include "lldb/Utility/DataBufferHeap.h"
+#include "lldb/Utility/DataExtractor.h"
+#include "lldb/Utility/StreamString.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+/// Valid programs tests
+
+static void
+CheckValidProgramTranslation(llvm::StringRef fpo_program,
+                             llvm::StringRef target_register_name,
+                             llvm::StringRef expected_dwarf_expression) {
+  // initial setup
+  ArchSpec arch_spec("i686-pc-windows");
+  llvm::Triple::ArchType arch_type = arch_spec.GetMachine();
+  ByteOrder byte_order = arch_spec.GetByteOrder();
+  uint32_t address_size = arch_spec.GetAddressByteSize();
+  uint32_t byte_size = arch_spec.GetDataByteSize();
+
+  // program translation
+  StreamBuffer<32> stream(Stream::eBinary, address_size, byte_order);
+  ASSERT_TRUE(TranslateFPOProgramToDWARFExpression(
+      fpo_program, target_register_name, arch_type, stream));
+
+  // print dwarf expression to comparable textual representation
+  DataBufferSP buffer =
+      std::make_shared<DataBufferHeap>(stream.GetData(), stream.GetSize());
+  DataExtractor extractor(buffer, byte_order, address_size, byte_size);
+
+  StreamString result_dwarf_expression;
+  ASSERT_TRUE(DWARFExpression::PrintDWARFExpression(
+      result_dwarf_expression, extractor, address_size, 4, false));
+
+  // actual check
+  ASSERT_STREQ(expected_dwarf_expression.data(),
+               result_dwarf_expression.GetString().data());
+}
+
+TEST(PDBFPOProgramToDWARFExpressionTests, SingleAssignmentConst) {
+  CheckValidProgramTranslation("$T0 0 = ", "$T0", "DW_OP_constu 0x0");
+}
+
+TEST(PDBFPOProgramToDWARFExpressionTests, SingleAssignmentRegisterRef) {
+  CheckValidProgramTranslation("$T0 $ebp = ", "$T0", "DW_OP_breg6 +0");
+}
+
+TEST(PDBFPOProgramToDWARFExpressionTests, SingleAssignmentExpressionPlus) {
+  CheckValidProgramTranslation("$T0 $ebp 4 + = ", "$T0",
+                               "DW_OP_breg6 +0, DW_OP_constu 0x4, DW_OP_plus ");
+}
+
+TEST(PDBFPOProgramToDWARFExpressionTests, SingleAssignmentExpressionDeref) {
+  CheckValidProgramTranslation("$T0 $ebp ^ = ", "$T0",
+                               "DW_OP_breg6 +0, DW_OP_deref ");
+}
+
+TEST(PDBFPOProgramToDWARFExpressionTests, SingleAssignmentExpressionMinus) {
+  CheckValidProgramTranslation(
+      "$T0 $ebp 4 - = ", "$T0",
+      "DW_OP_breg6 +0, DW_OP_constu 0x4, DW_OP_minus ");
+}
+
+TEST(PDBFPOProgramToDWARFExpressionTests, SingleAssignmentExpressionAlign) {
+  CheckValidProgramTranslation("$T0 $ebp 128 @ = ", "$T0",
+                               "DW_OP_breg6 +0, DW_OP_constu 0x80, DW_OP_lit1 "
+                               ", DW_OP_minus , DW_OP_not , DW_OP_and ");
+}
+
+TEST(PDBFPOProgramToDWARFExpressionTests, MultipleIndependentAssignments) {
+  CheckValidProgramTranslation("$T1 1 = $T0 0 =", "$T0", "DW_OP_constu 0x0");
+}
+
+TEST(PDBFPOProgramToDWARFExpressionTests, MultipleDependentAssignments) {
+  CheckValidProgramTranslation(
+      "$T1 $ebp 4 + = $T0 $T1 8 - 128 @ = ", "$T0",
+      "DW_OP_breg6 +0, DW_OP_constu 0x4, DW_OP_plus , DW_OP_constu 0x8, "
+      "DW_OP_minus , DW_OP_constu 0x80, DW_OP_lit1 , DW_OP_minus , DW_OP_not , "
+      "DW_OP_and ");
+}
+
+TEST(PDBFPOProgramToDWARFExpressionTests, DependencyChain) {
+  CheckValidProgramTranslation("$T1 0 = $T0 $T1 = $ebp $T0 =", "$ebp",
+                               "DW_OP_constu 0x0");
+}
+
+/// Invalid programs tests
+static void
+CheckInvalidProgramTranslation(llvm::StringRef fpo_program,
+                               llvm::StringRef target_register_name) {
+  // initial setup
+  ArchSpec arch_spec("i686-pc-windows");
+  llvm::Triple::ArchType arch_type = arch_spec.GetMachine();
+  ByteOrder byte_order = arch_spec.GetByteOrder();
+  uint32_t address_size = arch_spec.GetAddressByteSize();
+
+  // program translation
+  StreamBuffer<32> stream(Stream::eBinary, address_size, byte_order);
+  EXPECT_FALSE(TranslateFPOProgramToDWARFExpression(
+      fpo_program, target_register_name, arch_type, stream));
+  EXPECT_EQ(0, stream.GetSize());
+}
+
+TEST(PDBFPOProgramToDWARFExpressionTests, InvalidAssignmentSingle) {
+  CheckInvalidProgramTranslation("$T0 0", "$T0");
+}
+
+TEST(PDBFPOProgramToDWARFExpressionTests, InvalidAssignmentMultiple) {
+  CheckInvalidProgramTranslation("$T1 0 = $T0 0", "$T0");
+}
+
+TEST(PDBFPOProgramToDWARFExpressionTests, UnknownOp) {
+  CheckInvalidProgramTranslation("$T0 $ebp 0 & = ", "$T0");
+}
+
+TEST(PDBFPOProgramToDWARFExpressionTests, InvalidOpBinary) {
+  CheckInvalidProgramTranslation("$T0 0 + = ", "$T0");
+}
+
+TEST(PDBFPOProgramToDWARFExpressionTests, InvalidOpUnary) {
+  CheckInvalidProgramTranslation("$T0 ^ = ", "$T0");
+}
+
+TEST(PDBFPOProgramToDWARFExpressionTests, MissingTargetRegister) {
+  CheckInvalidProgramTranslation("$T1 0 = ", "$T0");
+}
+
+TEST(PDBFPOProgramToDWARFExpressionTests, UnresolvedRegisterReference) {
+  CheckInvalidProgramTranslation("$T0 $abc = ", "$T0");
+}
+
+TEST(PDBFPOProgramToDWARFExpressionTests,
+     UnresolvedRegisterAssignmentReference) {
+  CheckInvalidProgramTranslation("$T2 0 = $T0 $T1 = ", "$T0");
+}
+
+TEST(PDBFPOProgramToDWARFExpressionTests,
+     UnresolvedCyclicRegisterAssignmentReference) {
+  CheckInvalidProgramTranslation("$T1 $T0 = $T0 $T1 = ", "$T0");
+}
+
+TEST(PDBFPOProgramToDWARFExpressionTests,
+     UnresolvedDependentCyclicRegisterAssignmentReference) {
+  CheckInvalidProgramTranslation("$T1 $T0 = $T0 $T1 = $T2 $T1 =", "$T2");
+}
+
+TEST(PDBFPOProgramToDWARFExpressionTests, UnsupportedRASearch) {
+  CheckInvalidProgramTranslation("$T0 .raSearch = ", "$T0");
+}
Index: unittests/SymbolFile/NativePDB/CMakeLists.txt
===================================================================
--- /dev/null
+++ unittests/SymbolFile/NativePDB/CMakeLists.txt
@@ -0,0 +1,13 @@
+add_lldb_unittest(SymbolFileNativePDBTests
+  PdbFPOProgramToDWARFExpressionTests.cpp
+
+  LINK_LIBS
+    lldbCore
+    lldbHost
+    lldbSymbol
+    lldbPluginSymbolFileNativePDB
+    lldbUtilityHelpers
+  LINK_COMPONENTS
+    Support
+    DebugInfoPDB
+  )
Index: unittests/SymbolFile/CMakeLists.txt
===================================================================
--- unittests/SymbolFile/CMakeLists.txt
+++ unittests/SymbolFile/CMakeLists.txt
@@ -1,4 +1,5 @@
 add_subdirectory(DWARF)
+add_subdirectory(NativePDB)
 if (LLVM_ENABLE_DIA_SDK)
   add_subdirectory(PDB)
 endif()
Index: source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp
===================================================================
--- source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp
+++ source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp
@@ -934,12 +934,25 @@
 
   Variable::RangeList ranges;
   SymbolContextScope *context_scope = sc.comp_unit;
-  if (scope == eValueTypeVariableLocal) {
+  if (scope == eValueTypeVariableLocal || scope == eValueTypeVariableArgument) {
     if (sc.function) {
-      context_scope = sc.function->GetBlock(true).FindBlockByID(
-          pdb_data.getLexicalParentId());
-      if (context_scope == nullptr)
-        context_scope = sc.function;
+      Block &function_block = sc.function->GetBlock(true);
+      Block *block =
+          function_block.FindBlockByID(pdb_data.getLexicalParentId());
+      if (!block)
+        block = &function_block;
+
+      context_scope = block;
+
+      for (size_t i = 0, num_ranges = block->GetNumRanges(); i < num_ranges;
+           ++i) {
+        AddressRange range;
+        if (!block->GetRangeAtIndex(i, range))
+          continue;
+
+        ranges.Append(range.GetBaseAddress().GetFileAddress(),
+                      range.GetByteSize());
+      }
     }
   }
 
@@ -952,7 +965,7 @@
 
   bool is_constant;
   DWARFExpression location = ConvertPDBLocationToDWARFExpression(
-      GetObjectFile()->GetModule(), pdb_data, is_constant);
+      GetObjectFile()->GetModule(), pdb_data, ranges, is_constant);
 
   var_sp = std::make_shared<Variable>(
       var_uid, var_name.c_str(), mangled_cstr, type_sp, scope, context_scope,
Index: source/Plugins/SymbolFile/PDB/PDBLocationToDWARFExpression.h
===================================================================
--- source/Plugins/SymbolFile/PDB/PDBLocationToDWARFExpression.h
+++ source/Plugins/SymbolFile/PDB/PDBLocationToDWARFExpression.h
@@ -11,6 +11,7 @@
 #define lldb_Plugins_SymbolFile_PDB_PDBLocationToDWARFExpression_h_
 
 #include "lldb/Core/Module.h"
+#include "lldb/Symbol/Variable.h"
 
 namespace lldb_private {
 class DWARFExpression;
@@ -31,6 +32,9 @@
 /// @param[in] symbol
 ///     The symbol with a location information to convert.
 ///
+/// @param[in] ranges
+///     Ranges where this variable is valid.
+///
 /// @param[out] is_constant
 ///     Set to \b true if the result expression is a constant value data,
 ///     and \b false if it is a DWARF bytecode.
@@ -41,5 +45,6 @@
 lldb_private::DWARFExpression
 ConvertPDBLocationToDWARFExpression(lldb::ModuleSP module,
                                     const llvm::pdb::PDBSymbolData &symbol,
+                                    const lldb_private::Variable::RangeList &ranges,
                                     bool &is_constant);
 #endif
Index: source/Plugins/SymbolFile/PDB/PDBLocationToDWARFExpression.cpp
===================================================================
--- source/Plugins/SymbolFile/PDB/PDBLocationToDWARFExpression.cpp
+++ source/Plugins/SymbolFile/PDB/PDBLocationToDWARFExpression.cpp
@@ -13,483 +13,59 @@
 #include "lldb/Core/StreamBuffer.h"
 #include "lldb/Core/dwarf.h"
 #include "lldb/Expression/DWARFExpression.h"
+#include "lldb/Symbol/Variable.h"
 #include "lldb/Utility/DataBufferHeap.h"
 
 #include "llvm/DebugInfo/CodeView/CodeView.h"
+#include "llvm/DebugInfo/PDB/IPDBSession.h"
 #include "llvm/DebugInfo/PDB/PDBSymbolData.h"
 
-#include "Plugins/Process/Utility/lldb-x86-register-enums.h"
+#include "Plugins/SymbolFile/NativePDB/CodeViewRegisterMapping.h"
+#include "Plugins/SymbolFile/NativePDB/PdbFPOProgramToDWARFExpression.h"
 
 using namespace lldb;
 using namespace lldb_private;
 using namespace llvm::pdb;
 
-namespace {
-const uint32_t g_code_view_to_lldb_registers_x86[] = {
-    LLDB_INVALID_REGNUM, // NONE
-    lldb_al_i386,        // AL
-    lldb_cl_i386,        // CL
-    lldb_dl_i386,        // DL
-    lldb_bl_i386,        // BL
-    lldb_ah_i386,        // AH
-    lldb_ch_i386,        // CH
-    lldb_dh_i386,        // DH
-    lldb_bh_i386,        // BH
-    lldb_ax_i386,        // AX
-    lldb_cx_i386,        // CX
-    lldb_dx_i386,        // DX
-    lldb_bx_i386,        // BX
-    lldb_sp_i386,        // SP
-    lldb_bp_i386,        // BP
-    lldb_si_i386,        // SI
-    lldb_di_i386,        // DI
-    lldb_eax_i386,       // EAX
-    lldb_ecx_i386,       // ECX
-    lldb_edx_i386,       // EDX
-    lldb_ebx_i386,       // EBX
-    lldb_esp_i386,       // ESP
-    lldb_ebp_i386,       // EBP
-    lldb_esi_i386,       // ESI
-    lldb_edi_i386,       // EDI
-    lldb_es_i386,        // ES
-    lldb_cs_i386,        // CS
-    lldb_ss_i386,        // SS
-    lldb_ds_i386,        // DS
-    lldb_fs_i386,        // FS
-    lldb_gs_i386,        // GS
-    LLDB_INVALID_REGNUM, // IP
-    LLDB_INVALID_REGNUM, // FLAGS
-    lldb_eip_i386,       // EIP
-    lldb_eflags_i386,    // EFLAGS
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, // TEMP
-    LLDB_INVALID_REGNUM, // TEMPH
-    LLDB_INVALID_REGNUM, // QUOTE
-    LLDB_INVALID_REGNUM, // PCDR3
-    LLDB_INVALID_REGNUM, // PCDR4
-    LLDB_INVALID_REGNUM, // PCDR5
-    LLDB_INVALID_REGNUM, // PCDR6
-    LLDB_INVALID_REGNUM, // PCDR7
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, // CR0
-    LLDB_INVALID_REGNUM, // CR1
-    LLDB_INVALID_REGNUM, // CR2
-    LLDB_INVALID_REGNUM, // CR3
-    LLDB_INVALID_REGNUM, // CR4
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    lldb_dr0_i386, // DR0
-    lldb_dr1_i386, // DR1
-    lldb_dr2_i386, // DR2
-    lldb_dr3_i386, // DR3
-    lldb_dr4_i386, // DR4
-    lldb_dr5_i386, // DR5
-    lldb_dr6_i386, // DR6
-    lldb_dr7_i386, // DR7
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, // GDTR
-    LLDB_INVALID_REGNUM, // GDTL
-    LLDB_INVALID_REGNUM, // IDTR
-    LLDB_INVALID_REGNUM, // IDTL
-    LLDB_INVALID_REGNUM, // LDTR
-    LLDB_INVALID_REGNUM, // TR
-    LLDB_INVALID_REGNUM, // PSEUDO1
-    LLDB_INVALID_REGNUM, // PSEUDO2
-    LLDB_INVALID_REGNUM, // PSEUDO3
-    LLDB_INVALID_REGNUM, // PSEUDO4
-    LLDB_INVALID_REGNUM, // PSEUDO5
-    LLDB_INVALID_REGNUM, // PSEUDO6
-    LLDB_INVALID_REGNUM, // PSEUDO7
-    LLDB_INVALID_REGNUM, // PSEUDO8
-    LLDB_INVALID_REGNUM, // PSEUDO9
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    lldb_st0_i386,       // ST0
-    lldb_st1_i386,       // ST1
-    lldb_st2_i386,       // ST2
-    lldb_st3_i386,       // ST3
-    lldb_st4_i386,       // ST4
-    lldb_st5_i386,       // ST5
-    lldb_st6_i386,       // ST6
-    lldb_st7_i386,       // ST7
-    LLDB_INVALID_REGNUM, // CTRL
-    LLDB_INVALID_REGNUM, // STAT
-    LLDB_INVALID_REGNUM, // TAG
-    LLDB_INVALID_REGNUM, // FPIP
-    LLDB_INVALID_REGNUM, // FPCS
-    LLDB_INVALID_REGNUM, // FPDO
-    LLDB_INVALID_REGNUM, // FPDS
-    LLDB_INVALID_REGNUM, // ISEM
-    LLDB_INVALID_REGNUM, // FPEIP
-    LLDB_INVALID_REGNUM, // FPEDO
-    lldb_mm0_i386,       // MM0
-    lldb_mm1_i386,       // MM1
-    lldb_mm2_i386,       // MM2
-    lldb_mm3_i386,       // MM3
-    lldb_mm4_i386,       // MM4
-    lldb_mm5_i386,       // MM5
-    lldb_mm6_i386,       // MM6
-    lldb_mm7_i386,       // MM7
-    lldb_xmm0_i386,      // XMM0
-    lldb_xmm1_i386,      // XMM1
-    lldb_xmm2_i386,      // XMM2
-    lldb_xmm3_i386,      // XMM3
-    lldb_xmm4_i386,      // XMM4
-    lldb_xmm5_i386,      // XMM5
-    lldb_xmm6_i386,      // XMM6
-    lldb_xmm7_i386       // XMM7
-};
-
-const uint32_t g_code_view_to_lldb_registers_x86_64[] = {
-    LLDB_INVALID_REGNUM, // NONE
-    lldb_al_x86_64,      // AL
-    lldb_cl_x86_64,      // CL
-    lldb_dl_x86_64,      // DL
-    lldb_bl_x86_64,      // BL
-    lldb_ah_x86_64,      // AH
-    lldb_ch_x86_64,      // CH
-    lldb_dh_x86_64,      // DH
-    lldb_bh_x86_64,      // BH
-    lldb_ax_x86_64,      // AX
-    lldb_cx_x86_64,      // CX
-    lldb_dx_x86_64,      // DX
-    lldb_bx_x86_64,      // BX
-    lldb_sp_x86_64,      // SP
-    lldb_bp_x86_64,      // BP
-    lldb_si_x86_64,      // SI
-    lldb_di_x86_64,      // DI
-    lldb_eax_x86_64,     // EAX
-    lldb_ecx_x86_64,     // ECX
-    lldb_edx_x86_64,     // EDX
-    lldb_ebx_x86_64,     // EBX
-    lldb_esp_x86_64,     // ESP
-    lldb_ebp_x86_64,     // EBP
-    lldb_esi_x86_64,     // ESI
-    lldb_edi_x86_64,     // EDI
-    lldb_es_x86_64,      // ES
-    lldb_cs_x86_64,      // CS
-    lldb_ss_x86_64,      // SS
-    lldb_ds_x86_64,      // DS
-    lldb_fs_x86_64,      // FS
-    lldb_gs_x86_64,      // GS
-    LLDB_INVALID_REGNUM, // IP
-    LLDB_INVALID_REGNUM, // FLAGS
-    LLDB_INVALID_REGNUM, // EIP
-    LLDB_INVALID_REGNUM, // EFLAGS
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, // TEMP
-    LLDB_INVALID_REGNUM, // TEMPH
-    LLDB_INVALID_REGNUM, // QUOTE
-    LLDB_INVALID_REGNUM, // PCDR3
-    LLDB_INVALID_REGNUM, // PCDR4
-    LLDB_INVALID_REGNUM, // PCDR5
-    LLDB_INVALID_REGNUM, // PCDR6
-    LLDB_INVALID_REGNUM, // PCDR7
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, // CR0
-    LLDB_INVALID_REGNUM, // CR1
-    LLDB_INVALID_REGNUM, // CR2
-    LLDB_INVALID_REGNUM, // CR3
-    LLDB_INVALID_REGNUM, // CR4
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    lldb_dr0_x86_64, // DR0
-    lldb_dr1_x86_64, // DR1
-    lldb_dr2_x86_64, // DR2
-    lldb_dr3_x86_64, // DR3
-    lldb_dr4_x86_64, // DR4
-    lldb_dr5_x86_64, // DR5
-    lldb_dr6_x86_64, // DR6
-    lldb_dr7_x86_64, // DR7
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, // GDTR
-    LLDB_INVALID_REGNUM, // GDTL
-    LLDB_INVALID_REGNUM, // IDTR
-    LLDB_INVALID_REGNUM, // IDTL
-    LLDB_INVALID_REGNUM, // LDTR
-    LLDB_INVALID_REGNUM, // TR
-    LLDB_INVALID_REGNUM, // PSEUDO1
-    LLDB_INVALID_REGNUM, // PSEUDO2
-    LLDB_INVALID_REGNUM, // PSEUDO3
-    LLDB_INVALID_REGNUM, // PSEUDO4
-    LLDB_INVALID_REGNUM, // PSEUDO5
-    LLDB_INVALID_REGNUM, // PSEUDO6
-    LLDB_INVALID_REGNUM, // PSEUDO7
-    LLDB_INVALID_REGNUM, // PSEUDO8
-    LLDB_INVALID_REGNUM, // PSEUDO9
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    lldb_st0_x86_64,     // ST0
-    lldb_st1_x86_64,     // ST1
-    lldb_st2_x86_64,     // ST2
-    lldb_st3_x86_64,     // ST3
-    lldb_st4_x86_64,     // ST4
-    lldb_st5_x86_64,     // ST5
-    lldb_st6_x86_64,     // ST6
-    lldb_st7_x86_64,     // ST7
-    LLDB_INVALID_REGNUM, // CTRL
-    LLDB_INVALID_REGNUM, // STAT
-    LLDB_INVALID_REGNUM, // TAG
-    LLDB_INVALID_REGNUM, // FPIP
-    LLDB_INVALID_REGNUM, // FPCS
-    LLDB_INVALID_REGNUM, // FPDO
-    LLDB_INVALID_REGNUM, // FPDS
-    LLDB_INVALID_REGNUM, // ISEM
-    LLDB_INVALID_REGNUM, // FPEIP
-    LLDB_INVALID_REGNUM, // FPEDO
-    lldb_mm0_x86_64,     // MM0
-    lldb_mm1_x86_64,     // MM1
-    lldb_mm2_x86_64,     // MM2
-    lldb_mm3_x86_64,     // MM3
-    lldb_mm4_x86_64,     // MM4
-    lldb_mm5_x86_64,     // MM5
-    lldb_mm6_x86_64,     // MM6
-    lldb_mm7_x86_64,     // MM7
-    lldb_xmm0_x86_64,    // XMM0
-    lldb_xmm1_x86_64,    // XMM1
-    lldb_xmm2_x86_64,    // XMM2
-    lldb_xmm3_x86_64,    // XMM3
-    lldb_xmm4_x86_64,    // XMM4
-    lldb_xmm5_x86_64,    // XMM5
-    lldb_xmm6_x86_64,    // XMM6
-    lldb_xmm7_x86_64,    // XMM7
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM,
-    lldb_mxcsr_x86_64,   // MXCSR
-    LLDB_INVALID_REGNUM, // EDXEAX
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, // EMM0L
-    LLDB_INVALID_REGNUM, // EMM1L
-    LLDB_INVALID_REGNUM, // EMM2L
-    LLDB_INVALID_REGNUM, // EMM3L
-    LLDB_INVALID_REGNUM, // EMM4L
-    LLDB_INVALID_REGNUM, // EMM5L
-    LLDB_INVALID_REGNUM, // EMM6L
-    LLDB_INVALID_REGNUM, // EMM7L
-    LLDB_INVALID_REGNUM, // EMM0H
-    LLDB_INVALID_REGNUM, // EMM1H
-    LLDB_INVALID_REGNUM, // EMM2H
-    LLDB_INVALID_REGNUM, // EMM3H
-    LLDB_INVALID_REGNUM, // EMM4H
-    LLDB_INVALID_REGNUM, // EMM5H
-    LLDB_INVALID_REGNUM, // EMM6H
-    LLDB_INVALID_REGNUM, // EMM7H
-    LLDB_INVALID_REGNUM, // MM00
-    LLDB_INVALID_REGNUM, // MM01
-    LLDB_INVALID_REGNUM, // MM10
-    LLDB_INVALID_REGNUM, // MM11
-    LLDB_INVALID_REGNUM, // MM20
-    LLDB_INVALID_REGNUM, // MM21
-    LLDB_INVALID_REGNUM, // MM30
-    LLDB_INVALID_REGNUM, // MM31
-    LLDB_INVALID_REGNUM, // MM40
-    LLDB_INVALID_REGNUM, // MM41
-    LLDB_INVALID_REGNUM, // MM50
-    LLDB_INVALID_REGNUM, // MM51
-    LLDB_INVALID_REGNUM, // MM60
-    LLDB_INVALID_REGNUM, // MM61
-    LLDB_INVALID_REGNUM, // MM70
-    LLDB_INVALID_REGNUM, // MM71
-    lldb_xmm8_x86_64,    // XMM8
-    lldb_xmm9_x86_64,    // XMM9
-    lldb_xmm10_x86_64,   // XMM10
-    lldb_xmm11_x86_64,   // XMM11
-    lldb_xmm12_x86_64,   // XMM12
-    lldb_xmm13_x86_64,   // XMM13
-    lldb_xmm14_x86_64,   // XMM14
-    lldb_xmm15_x86_64,   // XMM15
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM,
-    lldb_sil_x86_64,   // SIL
-    lldb_dil_x86_64,   // DIL
-    lldb_bpl_x86_64,   // BPL
-    lldb_spl_x86_64,   // SPL
-    lldb_rax_x86_64,   // RAX
-    lldb_rbx_x86_64,   // RBX
-    lldb_rcx_x86_64,   // RCX
-    lldb_rdx_x86_64,   // RDX
-    lldb_rsi_x86_64,   // RSI
-    lldb_rdi_x86_64,   // RDI
-    lldb_rbp_x86_64,   // RBP
-    lldb_rsp_x86_64,   // RSP
-    lldb_r8_x86_64,    // R8
-    lldb_r9_x86_64,    // R9
-    lldb_r10_x86_64,   // R10
-    lldb_r11_x86_64,   // R11
-    lldb_r12_x86_64,   // R12
-    lldb_r13_x86_64,   // R13
-    lldb_r14_x86_64,   // R14
-    lldb_r15_x86_64,   // R15
-    lldb_r8l_x86_64,   // R8B
-    lldb_r9l_x86_64,   // R9B
-    lldb_r10l_x86_64,  // R10B
-    lldb_r11l_x86_64,  // R11B
-    lldb_r12l_x86_64,  // R12B
-    lldb_r13l_x86_64,  // R13B
-    lldb_r14l_x86_64,  // R14B
-    lldb_r15l_x86_64,  // R15B
-    lldb_r8w_x86_64,   // R8W
-    lldb_r9w_x86_64,   // R9W
-    lldb_r10w_x86_64,  // R10W
-    lldb_r11w_x86_64,  // R11W
-    lldb_r12w_x86_64,  // R12W
-    lldb_r13w_x86_64,  // R13W
-    lldb_r14w_x86_64,  // R14W
-    lldb_r15w_x86_64,  // R15W
-    lldb_r8d_x86_64,   // R8D
-    lldb_r9d_x86_64,   // R9D
-    lldb_r10d_x86_64,  // R10D
-    lldb_r11d_x86_64,  // R11D
-    lldb_r12d_x86_64,  // R12D
-    lldb_r13d_x86_64,  // R13D
-    lldb_r14d_x86_64,  // R14D
-    lldb_r15d_x86_64,  // R15D
-    lldb_ymm0_x86_64,  // AMD64_YMM0
-    lldb_ymm1_x86_64,  // AMD64_YMM1
-    lldb_ymm2_x86_64,  // AMD64_YMM2
-    lldb_ymm3_x86_64,  // AMD64_YMM3
-    lldb_ymm4_x86_64,  // AMD64_YMM4
-    lldb_ymm5_x86_64,  // AMD64_YMM5
-    lldb_ymm6_x86_64,  // AMD64_YMM6
-    lldb_ymm7_x86_64,  // AMD64_YMM7
-    lldb_ymm8_x86_64,  // AMD64_YMM8
-    lldb_ymm9_x86_64,  // AMD64_YMM9
-    lldb_ymm10_x86_64, // AMD64_YMM10
-    lldb_ymm11_x86_64, // AMD64_YMM11
-    lldb_ymm12_x86_64, // AMD64_YMM12
-    lldb_ymm13_x86_64, // AMD64_YMM13
-    lldb_ymm14_x86_64, // AMD64_YMM14
-    lldb_ymm15_x86_64, // AMD64_YMM15
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    lldb_bnd0_x86_64, // BND0
-    lldb_bnd1_x86_64, // BND1
-    lldb_bnd2_x86_64  // BND2
-};
-
-uint32_t GetLLDBRegisterNumber(llvm::Triple::ArchType arch_type,
-                               llvm::codeview::RegisterId register_id) {
-  switch (arch_type) {
-  case llvm::Triple::x86:
-    if (static_cast<uint16_t>(register_id) <
-        sizeof(g_code_view_to_lldb_registers_x86) /
-            sizeof(g_code_view_to_lldb_registers_x86[0]))
-      return g_code_view_to_lldb_registers_x86[static_cast<uint16_t>(
-          register_id)];
-
-    switch (register_id) {
-    case llvm::codeview::RegisterId::MXCSR:
-      return lldb_mxcsr_i386;
-    case llvm::codeview::RegisterId::BND0:
-      return lldb_bnd0_i386;
-    case llvm::codeview::RegisterId::BND1:
-      return lldb_bnd1_i386;
-    case llvm::codeview::RegisterId::BND2:
-      return lldb_bnd2_i386;
-    default:
-      return LLDB_INVALID_REGNUM;
+static std::unique_ptr<IPDBFrameData>
+GetCorrespondingFrameData(const IPDBSession &session,
+                          const Variable::RangeList &ranges) {
+  auto enumFrameData = session.getFrameData();
+  if (!enumFrameData)
+    return nullptr;
+
+  std::unique_ptr<IPDBFrameData> found;
+  while (auto fd = enumFrameData->getNext()) {
+    Range<lldb::addr_t, lldb::addr_t> fdRange(fd->getVirtualAddress(),
+                                              fd->getLengthBlock());
+
+    for (size_t i = 0; i < ranges.GetSize(); i++) {
+      auto range = ranges.GetEntryAtIndex(i);
+      if (!range)
+        continue;
+
+      if (!range->DoesIntersect(fdRange))
+        continue;
+
+      found = std::move(fd);
+
+      break;
     }
-  case llvm::Triple::x86_64:
-    if (static_cast<uint16_t>(register_id) <
-        sizeof(g_code_view_to_lldb_registers_x86_64) /
-            sizeof(g_code_view_to_lldb_registers_x86_64[0]))
-      return g_code_view_to_lldb_registers_x86_64[static_cast<uint16_t>(
-          register_id)];
-
-    return LLDB_INVALID_REGNUM;
-  default:
-    return LLDB_INVALID_REGNUM;
   }
-}
-
-uint32_t GetGenericRegisterNumber(llvm::codeview::RegisterId register_id) {
-  if (register_id == llvm::codeview::RegisterId::VFRAME)
-    return LLDB_REGNUM_GENERIC_FP;
 
-  return LLDB_INVALID_REGNUM;
+  return found;
 }
 
-uint32_t GetRegisterNumber(llvm::Triple::ArchType arch_type,
-                           llvm::codeview::RegisterId register_id,
-                           RegisterKind &register_kind) {
-  register_kind = eRegisterKindLLDB;
-  uint32_t reg_num = GetLLDBRegisterNumber(arch_type, register_id);
-  if (reg_num != LLDB_INVALID_REGNUM)
-    return reg_num;
-
-  register_kind = eRegisterKindGeneric;
-  return GetGenericRegisterNumber(register_id);
+static bool EmitVFrameEvaluationDWARFExpression(
+    llvm::StringRef program, llvm::Triple::ArchType arch_type, Stream &stream) {
+  // VFrame value always stored in $TO pseudo-register
+  return TranslateFPOProgramToDWARFExpression(program, "$T0", arch_type,
+                                              stream);
 }
-} // namespace
 
-DWARFExpression ConvertPDBLocationToDWARFExpression(ModuleSP module,
-                                                    const PDBSymbolData &symbol,
-                                                    bool &is_constant) {
+DWARFExpression ConvertPDBLocationToDWARFExpression(
+    ModuleSP module, const PDBSymbolData &symbol,
+    const Variable::RangeList &ranges, bool &is_constant) {
   is_constant = true;
 
   if (!module)
@@ -531,10 +107,32 @@
     break;
   }
   case PDB_LocType::RegRel: {
-    uint32_t reg_num =
-        GetRegisterNumber(arch_type, symbol.getRegisterId(), register_kind);
-    if (reg_num == LLDB_INVALID_REGNUM)
-      return DWARFExpression(nullptr);
+    uint32_t reg_num;
+    auto reg_id = symbol.getRegisterId();
+    if (reg_id == llvm::codeview::RegisterId::VFRAME) {
+      if (auto fd = GetCorrespondingFrameData(symbol.getSession(), ranges)) {
+        if (EmitVFrameEvaluationDWARFExpression(fd->getProgram(), arch_type,
+                                                stream)) {
+          int32_t offset = symbol.getOffset();
+          stream.PutHex8(DW_OP_consts);
+          stream.PutSLEB128(offset);
+          stream.PutHex8(DW_OP_plus);
+
+          register_kind = eRegisterKindLLDB;
+
+          is_constant = false;
+          break;
+        }
+      }
+
+      register_kind = eRegisterKindGeneric;
+      reg_num = LLDB_REGNUM_GENERIC_FP;
+    } else {
+      register_kind = eRegisterKindLLDB;
+      reg_num = GetLLDBRegisterNumber(arch_type, reg_id);
+      if (reg_num == LLDB_INVALID_REGNUM)
+        return DWARFExpression(nullptr);
+    }
 
     if (reg_num > 31) {
       stream.PutHex8(DW_OP_bregx);
@@ -550,8 +148,8 @@
     break;
   }
   case PDB_LocType::Enregistered: {
-    uint32_t reg_num =
-        GetRegisterNumber(arch_type, symbol.getRegisterId(), register_kind);
+    register_kind = eRegisterKindLLDB;
+    uint32_t reg_num = GetLLDBRegisterNumber(arch_type, symbol.getRegisterId());
     if (reg_num == LLDB_INVALID_REGNUM)
       return DWARFExpression(nullptr);
 
Index: source/Plugins/SymbolFile/PDB/CMakeLists.txt
===================================================================
--- source/Plugins/SymbolFile/PDB/CMakeLists.txt
+++ source/Plugins/SymbolFile/PDB/CMakeLists.txt
@@ -8,7 +8,7 @@
     clangLex
     lldbCore
     lldbSymbol
-	lldbUtility
+    lldbUtility
   lldbPluginSymbolFileNativePDB
   LINK_COMPONENTS
     DebugInfoPDB
Index: source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
===================================================================
--- source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
+++ source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
@@ -1316,7 +1316,9 @@
                                                     PdbCompilandSymId var_id,
                                                     bool is_param) {
   ModuleSP module = GetObjectFile()->GetModule();
-  VariableInfo var_info = GetVariableLocationInfo(*m_index, var_id, module);
+  Block &block = GetOrCreateBlock(scope_id);
+  VariableInfo var_info =
+      GetVariableLocationInfo(*m_index, var_id, block, module);
   if (!var_info.location || !var_info.ranges)
     return nullptr;
 
Index: source/Plugins/SymbolFile/NativePDB/PdbUtil.h
===================================================================
--- source/Plugins/SymbolFile/NativePDB/PdbUtil.h
+++ source/Plugins/SymbolFile/NativePDB/PdbUtil.h
@@ -142,7 +142,7 @@
 llvm::StringRef DropNameScope(llvm::StringRef name);
 
 VariableInfo GetVariableNameInfo(llvm::codeview::CVSymbol symbol);
-VariableInfo GetVariableLocationInfo(PdbIndex &index, PdbCompilandSymId var_id,
+VariableInfo GetVariableLocationInfo(PdbIndex &index, PdbCompilandSymId var_id, Block& block,
                                      lldb::ModuleSP module);
 
 size_t GetTypeSizeForSimpleKind(llvm::codeview::SimpleTypeKind kind);
Index: source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp
===================================================================
--- source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp
+++ source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp
@@ -15,9 +15,11 @@
 
 #include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
 #include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
+#include "llvm/DebugInfo/PDB/Native/DbiStream.h"
 #include "llvm/DebugInfo/PDB/Native/TpiStream.h"
 
 #include "Plugins/Language/CPlusPlus/MSVCUndecoratedNameParser.h"
+#include "lldb/Symbol/Block.h"
 #include "lldb/Utility/LLDBAssert.h"
 #include "lldb/lldb-enumerations.h"
 
@@ -43,7 +45,7 @@
     gaps = gaps.drop_front();
   }
 
-  result.Append(start, end);
+  result.Append(start, end - start);
   return result;
 }
 
@@ -507,8 +509,78 @@
   return {};
 }
 
+static auto
+GetCorrespondingFrameData(lldb::addr_t load_addr,
+                          const DebugFrameDataSubsectionRef &fpo_data,
+                          const Variable::RangeList &ranges) {
+  lldbassert(!ranges.IsEmpty());
+
+  // assume that all variable ranges correspond to one frame data
+  using RangeListEntry = Variable::RangeList::Entry;
+  const RangeListEntry &range = ranges.GetEntryRef(0);
+
+  auto it = fpo_data.begin();
+
+  // start by searching first frame data range containing variable range
+  for (; it != fpo_data.end(); ++it) {
+    RangeListEntry fd_range(load_addr + it->RvaStart, it->CodeSize);
+
+    if (fd_range.Contains(range)) {
+      break;
+    }
+  }
+
+  // then first most nested entry that still contains variable range
+  auto found = it;
+  for (; it != fpo_data.end(); ++it) {
+    RangeListEntry fd_range(load_addr + it->RvaStart, it->CodeSize);
+
+    if (!fd_range.Contains(range)) {
+      break;
+    }
+    found = it;
+  }
+
+  return found;
+}
+
+static bool GetFrameDataProgram(PdbIndex &index,
+                                const Variable::RangeList &ranges,
+                                llvm::StringRef &out_program) {
+  const DebugFrameDataSubsectionRef &new_fpo_data =
+      index.dbi().getNewFpoRecords();
+
+  auto frame_data_it =
+      GetCorrespondingFrameData(index.GetLoadAddress(), new_fpo_data, ranges);
+  if (frame_data_it == new_fpo_data.end())
+    return false;
+
+  PDBStringTable &strings = cantFail(index.pdb().getStringTable());
+  out_program = cantFail(strings.getStringForID(frame_data_it->FrameFunc));
+  return true;
+}
+
+static RegisterId GetBaseFrameRegister(PdbIndex &index,
+                                       PdbCompilandSymId frame_proc_id,
+                                       bool is_parameter) {
+  CVSymbol frame_proc_cvs = index.ReadSymbolRecord(frame_proc_id);
+  lldbassert(frame_proc_cvs.kind() == S_FRAMEPROC);
+
+  FrameProcSym frame_proc(SymbolRecordKind::FrameProcSym);
+  cantFail(SymbolDeserializer::deserializeAs<FrameProcSym>(frame_proc_cvs,
+                                                           frame_proc));
+
+  CPUType cpu_type = index.compilands()
+                         .GetCompiland(frame_proc_id.modi)
+                         ->m_compile_opts->Machine;
+
+  return is_parameter ? frame_proc.getParamFramePtrReg(cpu_type)
+                      : frame_proc.getLocalFramePtrReg(cpu_type);
+}
+
 VariableInfo lldb_private::npdb::GetVariableLocationInfo(
-    PdbIndex &index, PdbCompilandSymId var_id, lldb::ModuleSP module) {
+    PdbIndex &index, PdbCompilandSymId var_id, Block &block,
+    lldb::ModuleSP module) {
 
   CVSymbol sym = index.ReadSymbolRecord(var_id);
 
@@ -543,13 +615,69 @@
           SymbolRecordKind::DefRangeFramePointerRelSym);
       cantFail(SymbolDeserializer::deserializeAs<DefRangeFramePointerRelSym>(
           loc_specifier_cvs, loc));
-      // FIXME: The register needs to come from the S_FRAMEPROC symbol.
-      result.location =
-          MakeRegRelLocationExpression(RegisterId::RSP, loc.Offset, module);
-      result.ranges = MakeRangeList(index, loc.Range, loc.Gaps);
-    } else {
-      // FIXME: Handle other kinds
+
+      Variable::RangeList ranges = MakeRangeList(index, loc.Range, loc.Gaps);
+
+      // TODO: may be better to pass function scope and not lookup it every
+      // time? find nearest parent function block
+      Block *cur = &block;
+      while (cur->GetParent()) {
+        cur = cur->GetParent();
+      }
+      PdbCompilandSymId func_scope_id =
+          PdbSymUid(cur->GetID()).asCompilandSym();
+      CVSymbol func_block_cvs = index.ReadSymbolRecord(func_scope_id);
+      lldbassert(func_block_cvs.kind() == S_GPROC32 ||
+                 func_block_cvs.kind() == S_LPROC32);
+
+      PdbCompilandSymId frame_proc_id(
+          func_scope_id.modi, func_scope_id.offset + func_block_cvs.length());
+
+      bool is_parameter =
+          ((local.Flags & LocalSymFlags::IsParameter) != LocalSymFlags::None);
+      RegisterId base_reg =
+          GetBaseFrameRegister(index, frame_proc_id, is_parameter);
+
+      if (base_reg == RegisterId::VFRAME) {
+        llvm::StringRef program;
+        if (GetFrameDataProgram(index, ranges, program)) {
+          result.location =
+              MakeVFrameRelLocationExpression(program, loc.Offset, module);
+          result.ranges = std::move(ranges);
+        } else {
+          // invalid variable
+        }
+      } else {
+        result.location =
+            MakeRegRelLocationExpression(base_reg, loc.Offset, module);
+        result.ranges = std::move(ranges);
+      }
+    } else if (loc_specifier_cvs.kind() == S_DEFRANGE_REGISTER_REL) {
+      DefRangeRegisterRelSym loc(SymbolRecordKind::DefRangeRegisterRelSym);
+      cantFail(SymbolDeserializer::deserializeAs<DefRangeRegisterRelSym>(
+          loc_specifier_cvs, loc));
+
+      Variable::RangeList ranges = MakeRangeList(index, loc.Range, loc.Gaps);
+
+      RegisterId base_reg = (RegisterId)(uint16_t)loc.Hdr.Register;
+
+      if (base_reg == RegisterId::VFRAME) {
+        llvm::StringRef program;
+        if (GetFrameDataProgram(index, ranges, program)) {
+          result.location = MakeVFrameRelLocationExpression(
+              program, loc.Hdr.BasePointerOffset, module);
+          result.ranges = std::move(ranges);
+        } else {
+          // invalid variable
+        }
+      } else {
+        result.location = MakeRegRelLocationExpression(
+            base_reg, loc.Hdr.BasePointerOffset, module);
+        result.ranges = std::move(ranges);
+      }
     }
+
+    // FIXME: Handle other kinds
     return result;
   }
   llvm_unreachable("Symbol is not a local variable!");
Index: source/Plugins/SymbolFile/NativePDB/PdbIndex.h
===================================================================
--- source/Plugins/SymbolFile/NativePDB/PdbIndex.h
+++ source/Plugins/SymbolFile/NativePDB/PdbIndex.h
@@ -115,6 +115,7 @@
       create(std::unique_ptr<llvm::pdb::PDBFile>);
 
   void SetLoadAddress(lldb::addr_t addr) { m_load_address = addr; }
+  lldb::addr_t GetLoadAddress() const { return m_load_address; }
   void ParseSectionContribs();
 
   llvm::pdb::PDBFile &pdb() { return *m_file; }
Index: source/Plugins/SymbolFile/NativePDB/PdbFPOProgramToDWARFExpression.h
===================================================================
--- /dev/null
+++ source/Plugins/SymbolFile/NativePDB/PdbFPOProgramToDWARFExpression.h
@@ -0,0 +1,25 @@
+//===-- PDBFPOProgramToDWARFExpression.h ------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef lldb_Plugins_SymbolFile_PDB_PDBFPOProgramToDWARFExpression_h_
+#define lldb_Plugins_SymbolFile_PDB_PDBFPOProgramToDWARFExpression_h_
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/Triple.h"
+
+namespace lldb_private {
+class Stream;
+}
+
+bool TranslateFPOProgramToDWARFExpression(llvm::StringRef program,
+                                          llvm::StringRef register_name,
+                                          llvm::Triple::ArchType arch_type,
+                                          lldb_private::Stream &stream);
+
+#endif
Index: source/Plugins/SymbolFile/NativePDB/PdbFPOProgramToDWARFExpression.cpp
===================================================================
--- /dev/null
+++ source/Plugins/SymbolFile/NativePDB/PdbFPOProgramToDWARFExpression.cpp
@@ -0,0 +1,529 @@
+//===-- PDBFPOProgramToDWARFExpression.cpp ----------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "PDBFPOProgramToDWARFExpression.h"
+#include "CodeViewRegisterMapping.h"
+
+#include "lldb/Core/StreamBuffer.h"
+#include "lldb/Core/dwarf.h"
+#include "lldb/Utility/LLDBAssert.h"
+#include "lldb/Utility/Stream.h"
+#include "llvm/ADT/DenseMap.h"
+
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/DebugInfo/CodeView/CodeView.h"
+#include "llvm/DebugInfo/CodeView/EnumTables.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+namespace {
+
+class FPOProgramNode;
+class FPOProgramASTVisitor;
+
+class FPOProgramNode {
+public:
+  enum Kind {
+    Register,
+    IntegerLiteral,
+    BinaryOp,
+    UnaryOp,
+  };
+
+protected:
+  FPOProgramNode(Kind kind) : m_token_kind(kind) {}
+
+public:
+  virtual ~FPOProgramNode() = default;
+  virtual void Accept(FPOProgramASTVisitor *visitor) = 0;
+
+  Kind GetKind() const { return m_token_kind; }
+
+private:
+  Kind m_token_kind;
+};
+
+class FPOProgramNodeRegisterRef : public FPOProgramNode {
+public:
+  FPOProgramNodeRegisterRef(llvm::StringRef name)
+      : FPOProgramNode(Register), m_name(name) {}
+
+  void Accept(FPOProgramASTVisitor *visitor) override;
+
+  llvm::StringRef GetName() const { return m_name; }
+  uint32_t GetLLDBRegNum() const { return m_lldb_reg_num; }
+
+  bool ResolveLLDBRegisterNum(llvm::Triple::ArchType arch_type);
+
+private:
+  llvm::StringRef m_name;
+  uint32_t m_lldb_reg_num = LLDB_INVALID_REGNUM;
+};
+
+bool FPOProgramNodeRegisterRef::ResolveLLDBRegisterNum(
+    llvm::Triple::ArchType arch_type) {
+
+  llvm::StringRef reg_name = m_name.slice(1, m_name.size());
+
+  // lookup register name to get lldb register number
+  llvm::ArrayRef<llvm::EnumEntry<uint16_t>> register_names =
+      llvm::codeview::getRegisterNames();
+  auto it = llvm::find_if(
+      register_names,
+      [&reg_name](const llvm::EnumEntry<uint16_t> &register_entry) {
+        return reg_name.compare_lower(register_entry.Name) == 0;
+      });
+
+  if (it == register_names.end()) {
+    return false;
+  }
+
+  auto reg_id = static_cast<llvm::codeview::RegisterId>(it->Value);
+  m_lldb_reg_num = GetLLDBRegisterNumber(arch_type, reg_id);
+
+  return m_lldb_reg_num != LLDB_INVALID_REGNUM;
+}
+
+class FPOProgramNodeIntegerLiteral : public FPOProgramNode {
+public:
+  FPOProgramNodeIntegerLiteral(uint32_t value)
+      : FPOProgramNode(IntegerLiteral), m_value(value) {}
+
+  void Accept(FPOProgramASTVisitor *visitor) override;
+
+  uint32_t GetValue() const { return m_value; }
+
+private:
+  uint32_t m_value;
+};
+
+class FPOProgramNodeBinaryOp : public FPOProgramNode {
+public:
+  enum OpType {
+    Plus,
+    Minus,
+    Align,
+  };
+
+  FPOProgramNodeBinaryOp(OpType op_type, FPOProgramNode *left,
+                         FPOProgramNode *right)
+      : FPOProgramNode(BinaryOp), m_op_type(op_type), m_left(left),
+        m_right(right) {}
+
+  void Accept(FPOProgramASTVisitor *visitor) override;
+
+  OpType GetOpType() const { return m_op_type; }
+
+  const FPOProgramNode *Left() const { return m_left; }
+  FPOProgramNode *&Left() { return m_left; }
+
+  const FPOProgramNode *Right() const { return m_right; }
+  FPOProgramNode *&Right() { return m_right; }
+
+private:
+  OpType m_op_type;
+  FPOProgramNode *m_left;
+  FPOProgramNode *m_right;
+};
+
+class FPOProgramNodeUnaryOp : public FPOProgramNode {
+public:
+  enum OpType {
+    Deref,
+  };
+
+  FPOProgramNodeUnaryOp(OpType op_type, FPOProgramNode *operand)
+      : FPOProgramNode(UnaryOp), m_op_type(op_type), m_operand(operand) {}
+
+  void Accept(FPOProgramASTVisitor *visitor) override;
+
+  OpType GetOpType() const { return m_op_type; }
+
+  const FPOProgramNode *Operand() const { return m_operand; }
+  FPOProgramNode *&Operand() { return m_operand; }
+
+private:
+  OpType m_op_type;
+  FPOProgramNode *m_operand;
+};
+
+class FPOProgramASTVisitor {
+public:
+  virtual ~FPOProgramASTVisitor() = default;
+
+  virtual void Visit(FPOProgramNodeRegisterRef *node) {}
+  virtual void Visit(FPOProgramNodeIntegerLiteral *node) {}
+  virtual void Visit(FPOProgramNodeBinaryOp *node) {}
+  virtual void Visit(FPOProgramNodeUnaryOp *node) {}
+};
+
+void FPOProgramNodeRegisterRef::Accept(FPOProgramASTVisitor *visitor) {
+  visitor->Visit(this);
+}
+
+void FPOProgramNodeIntegerLiteral::Accept(FPOProgramASTVisitor *visitor) {
+  visitor->Visit(this);
+}
+
+void FPOProgramNodeBinaryOp::Accept(FPOProgramASTVisitor *visitor) {
+  visitor->Visit(this);
+}
+
+void FPOProgramNodeUnaryOp::Accept(FPOProgramASTVisitor *visitor) {
+  visitor->Visit(this);
+}
+
+class FPOProgramASTVisitorMergeDependent : public FPOProgramASTVisitor {
+public:
+  FPOProgramASTVisitorMergeDependent(
+      const llvm::DenseMap<llvm::StringRef, FPOProgramNode *>
+          &dependent_programs)
+      : m_dependent_programs(dependent_programs) {}
+
+  void Merge(FPOProgramNode *&node_ref);
+
+private:
+  void Visit(FPOProgramNodeRegisterRef *node) override {}
+  void Visit(FPOProgramNodeIntegerLiteral *node) override {}
+  void Visit(FPOProgramNodeBinaryOp *node) override;
+  void Visit(FPOProgramNodeUnaryOp *node) override;
+
+  void TryReplace(FPOProgramNode *&node_ref) const;
+
+private:
+  const llvm::DenseMap<llvm::StringRef, FPOProgramNode *> &m_dependent_programs;
+};
+
+void FPOProgramASTVisitorMergeDependent::Merge(FPOProgramNode *&node_ref) {
+  TryReplace(node_ref);
+  node_ref->Accept(this);
+}
+
+void FPOProgramASTVisitorMergeDependent::Visit(FPOProgramNodeBinaryOp *node) {
+  Merge(node->Left());
+  Merge(node->Right());
+}
+void FPOProgramASTVisitorMergeDependent::Visit(FPOProgramNodeUnaryOp *node) {
+  Merge(node->Operand());
+}
+
+void FPOProgramASTVisitorMergeDependent::TryReplace(
+    FPOProgramNode *&node_ref) const {
+
+  while (node_ref->GetKind() == FPOProgramNode::Register) {
+    auto *node_register_ref =
+        static_cast<FPOProgramNodeRegisterRef *>(node_ref);
+
+    auto it = m_dependent_programs.find(node_register_ref->GetName());
+    if (it == m_dependent_programs.end()) {
+      break;
+    }
+
+    node_ref = it->second;
+  }
+}
+
+class FPOProgramASTVisitorResolveRegisterRefs : public FPOProgramASTVisitor {
+public:
+  FPOProgramASTVisitorResolveRegisterRefs(
+      const llvm::DenseMap<llvm::StringRef, FPOProgramNode *>
+          &dependent_programs,
+      llvm::Triple::ArchType arch_type)
+      : m_dependent_programs(dependent_programs), m_arch_type(arch_type) {}
+
+  bool Resolve(FPOProgramNode *program);
+
+private:
+  void Visit(FPOProgramNodeRegisterRef *node) override;
+  void Visit(FPOProgramNodeIntegerLiteral *node) override {}
+  void Visit(FPOProgramNodeBinaryOp *node) override;
+  void Visit(FPOProgramNodeUnaryOp *node) override;
+
+private:
+  const llvm::DenseMap<llvm::StringRef, FPOProgramNode *> &m_dependent_programs;
+  llvm::Triple::ArchType m_arch_type;
+  bool m_no_error_flag = true;
+};
+
+bool FPOProgramASTVisitorResolveRegisterRefs::Resolve(FPOProgramNode *program) {
+  program->Accept(this);
+  return m_no_error_flag;
+}
+
+void FPOProgramASTVisitorResolveRegisterRefs::Visit(
+    FPOProgramNodeRegisterRef *node) {
+
+  // lookup register reference as lvalue in predecedent assignments
+  auto it = m_dependent_programs.find(node->GetName());
+  if (it != m_dependent_programs.end()) {
+    // dependent programs are already resolved and valid
+    return;
+  }
+  // try to resolve register reference as lldb register name
+  m_no_error_flag = node->ResolveLLDBRegisterNum(m_arch_type);
+}
+
+void FPOProgramASTVisitorResolveRegisterRefs::Visit(
+    FPOProgramNodeBinaryOp *node) {
+  m_no_error_flag = Resolve(node->Left()) && Resolve(node->Right());
+}
+
+void FPOProgramASTVisitorResolveRegisterRefs::Visit(
+    FPOProgramNodeUnaryOp *node) {
+  m_no_error_flag = Resolve(node->Operand());
+}
+
+class FPOProgramASTVisitorDWARFCodegen : public FPOProgramASTVisitor {
+public:
+  FPOProgramASTVisitorDWARFCodegen(Stream &stream) : m_out_stream(stream) {}
+
+  void Emit(FPOProgramNode *program);
+
+private:
+  void Visit(FPOProgramNodeRegisterRef *node) override;
+  void Visit(FPOProgramNodeIntegerLiteral *node) override;
+  void Visit(FPOProgramNodeBinaryOp *node) override;
+  void Visit(FPOProgramNodeUnaryOp *node) override;
+
+private:
+  Stream &m_out_stream;
+};
+
+void FPOProgramASTVisitorDWARFCodegen::Emit(FPOProgramNode *program) {
+  program->Accept(this);
+}
+
+void FPOProgramASTVisitorDWARFCodegen::Visit(FPOProgramNodeRegisterRef *node) {
+
+  uint32_t reg_num = node->GetLLDBRegNum();
+  lldbassert(reg_num != LLDB_INVALID_REGNUM);
+
+  if (reg_num > 31) {
+    m_out_stream.PutHex8(DW_OP_bregx);
+    m_out_stream.PutULEB128(reg_num);
+  } else
+    m_out_stream.PutHex8(DW_OP_breg0 + reg_num);
+
+  m_out_stream.PutSLEB128(0);
+}
+
+void FPOProgramASTVisitorDWARFCodegen::Visit(
+    FPOProgramNodeIntegerLiteral *node) {
+  uint32_t value = node->GetValue();
+  m_out_stream.PutHex8(DW_OP_constu);
+  m_out_stream.PutULEB128(value);
+}
+
+void FPOProgramASTVisitorDWARFCodegen::Visit(FPOProgramNodeBinaryOp *node) {
+
+  Emit(node->Left());
+  Emit(node->Right());
+
+  switch (node->GetOpType()) {
+  case FPOProgramNodeBinaryOp::Plus:
+    m_out_stream.PutHex8(DW_OP_plus);
+    // NOTE: can be optimized by using DW_OP_plus_uconst opcpode
+    //       if right child node is constant value
+    break;
+  case FPOProgramNodeBinaryOp::Minus:
+    m_out_stream.PutHex8(DW_OP_minus);
+    break;
+  case FPOProgramNodeBinaryOp::Align:
+    // emit align operator a @ b as
+    // a & ~(b - 1)
+    // NOTE: implicitly assuming that b is power of 2
+    m_out_stream.PutHex8(DW_OP_lit1);
+    m_out_stream.PutHex8(DW_OP_minus);
+    m_out_stream.PutHex8(DW_OP_not);
+
+    m_out_stream.PutHex8(DW_OP_and);
+    break;
+  }
+}
+
+void FPOProgramASTVisitorDWARFCodegen::Visit(FPOProgramNodeUnaryOp *node) {
+  Emit(node->Operand());
+
+  switch (node->GetOpType()) {
+  case FPOProgramNodeUnaryOp::Deref:
+    m_out_stream.PutHex8(DW_OP_deref);
+    break;
+  }
+}
+
+class NodeAllocator {
+public:
+  template <typename T, typename... Args> T *makeNode(Args &&... args) {
+    void *new_node_mem = m_alloc.Allocate(sizeof(T), alignof(T));
+    return new (new_node_mem) T(std::forward<Args>(args)...);
+  }
+
+private:
+  llvm::BumpPtrAllocator m_alloc;
+};
+
+} // namespace
+
+static bool ParseFPOSingleAssignmentProgram(llvm::StringRef program,
+                                            NodeAllocator &alloc,
+                                            llvm::StringRef &register_name,
+                                            FPOProgramNode *&ast) {
+  llvm::SmallVector<llvm::StringRef, 16> tokens;
+  llvm::SplitString(program, tokens, " ");
+
+  if (tokens.empty())
+    return false;
+
+  llvm::SmallVector<FPOProgramNode *, 4> eval_stack;
+
+  llvm::DenseMap<llvm::StringRef, FPOProgramNodeBinaryOp::OpType> ops_binary = {
+      {"+", FPOProgramNodeBinaryOp::Plus},
+      {"-", FPOProgramNodeBinaryOp::Minus},
+      {"@", FPOProgramNodeBinaryOp::Align},
+  };
+
+  llvm::DenseMap<llvm::StringRef, FPOProgramNodeUnaryOp::OpType> ops_unary = {
+      {"^", FPOProgramNodeUnaryOp::Deref},
+  };
+
+  constexpr llvm::StringLiteral ra_search_keyword = ".raSearch";
+
+  // lvalue of assignment is always first token
+  // rvalue program goes next
+  for (size_t i = 1; i < tokens.size(); ++i) {
+    llvm::StringRef cur = tokens[i];
+
+    auto ops_binary_it = ops_binary.find(cur);
+    if (ops_binary_it != ops_binary.end()) {
+      // token is binary operator
+      if (eval_stack.size() < 2) {
+        return false;
+      }
+      FPOProgramNode *right = eval_stack.pop_back_val();
+      FPOProgramNode *left = eval_stack.pop_back_val();
+      FPOProgramNode *node = alloc.makeNode<FPOProgramNodeBinaryOp>(
+          ops_binary_it->second, left, right);
+      eval_stack.push_back(node);
+      continue;
+    }
+
+    auto ops_unary_it = ops_unary.find(cur);
+    if (ops_unary_it != ops_unary.end()) {
+      // token is unary operator
+      if (eval_stack.empty()) {
+        return false;
+      }
+      FPOProgramNode *operand = eval_stack.pop_back_val();
+      FPOProgramNode *node =
+          alloc.makeNode<FPOProgramNodeUnaryOp>(ops_unary_it->second, operand);
+      eval_stack.push_back(node);
+      continue;
+    }
+
+    if (cur.startswith("$")) {
+      // token is register ref
+      eval_stack.push_back(alloc.makeNode<FPOProgramNodeRegisterRef>(cur));
+      continue;
+    }
+
+    if (cur == ra_search_keyword) {
+      // TODO: .raSearch is unsupported
+      return false;
+    }
+
+    uint32_t value;
+    if (!cur.getAsInteger(10, value)) {
+      // token is integer literal
+      eval_stack.push_back(alloc.makeNode<FPOProgramNodeIntegerLiteral>(value));
+      continue;
+    }
+
+    // unexpected token
+    return false;
+  }
+
+  if (eval_stack.size() != 1) {
+    return false;
+  }
+
+  register_name = tokens[0];
+  ast = eval_stack.pop_back_val();
+
+  return true;
+}
+
+static FPOProgramNode *ParseFPOProgram(llvm::StringRef program,
+                                       llvm::StringRef register_name,
+                                       llvm::Triple::ArchType arch_type,
+                                       NodeAllocator &alloc) {
+  llvm::DenseMap<llvm::StringRef, FPOProgramNode *> dependent_programs;
+
+  size_t cur = 0;
+  while (true) {
+    size_t assign_index = program.find('=', cur);
+    if (assign_index == llvm::StringRef::npos) {
+      llvm::StringRef tail = program.slice(cur, llvm::StringRef::npos);
+      if (!tail.trim().empty()) {
+        // missing assign operator
+        return nullptr;
+      }
+      break;
+    }
+    llvm::StringRef assignment_program = program.slice(cur, assign_index);
+
+    llvm::StringRef lvalue_name;
+    FPOProgramNode *rvalue_ast = nullptr;
+    if (!ParseFPOSingleAssignmentProgram(assignment_program, alloc, lvalue_name,
+                                         rvalue_ast)) {
+      return nullptr;
+    }
+
+    lldbassert(rvalue_ast);
+
+    // check & resolve assignment program
+    FPOProgramASTVisitorResolveRegisterRefs resolver(dependent_programs,
+                                                     arch_type);
+    if (!resolver.Resolve(rvalue_ast)) {
+      return nullptr;
+    }
+
+    if (lvalue_name == register_name) {
+      // found target assignment program - no need to parse further
+
+      // emplace valid dependent subtrees to make target assignment independent
+      // from predecessors
+      FPOProgramASTVisitorMergeDependent merger(dependent_programs);
+      merger.Merge(rvalue_ast);
+
+      return rvalue_ast;
+    }
+
+    dependent_programs[lvalue_name] = rvalue_ast;
+    cur = assign_index + 1;
+  }
+
+  return nullptr;
+}
+
+bool TranslateFPOProgramToDWARFExpression(llvm::StringRef program,
+                                          llvm::StringRef register_name,
+                                          llvm::Triple::ArchType arch_type,
+                                          Stream &stream) {
+  NodeAllocator node_alloc;
+  FPOProgramNode *target_program =
+      ParseFPOProgram(program, register_name, arch_type, node_alloc);
+  if (target_program == nullptr) {
+    return false;
+  }
+
+  FPOProgramASTVisitorDWARFCodegen codegen(stream);
+  codegen.Emit(target_program);
+  return true;
+}
Index: source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.h
===================================================================
--- source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.h
+++ source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.h
@@ -31,6 +31,9 @@
 DWARFExpression MakeRegRelLocationExpression(llvm::codeview::RegisterId reg,
                                              int32_t offset,
                                              lldb::ModuleSP module);
+DWARFExpression MakeVFrameRelLocationExpression(llvm::StringRef fpo_program,
+                                                int32_t offset,
+                                                lldb::ModuleSP module);
 DWARFExpression MakeGlobalLocationExpression(uint16_t section, uint32_t offset,
                                              lldb::ModuleSP module);
 DWARFExpression MakeConstantLocationExpression(
Index: source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.cpp
===================================================================
--- source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.cpp
+++ source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.cpp
@@ -9,7 +9,6 @@
 
 #include "DWARFLocationExpression.h"
 
-#include "Plugins/Process/Utility/lldb-x86-register-enums.h"
 #include "lldb/Core/Module.h"
 #include "lldb/Core/Section.h"
 #include "lldb/Core/StreamBuffer.h"
@@ -24,6 +23,8 @@
 #include "llvm/Support/Endian.h"
 
 #include "PdbUtil.h"
+#include "CodeViewRegisterMapping.h"
+#include "PdbFPOProgramToDWARFExpression.h"
 
 using namespace lldb;
 using namespace lldb_private;
@@ -31,448 +32,6 @@
 using namespace llvm::codeview;
 using namespace llvm::pdb;
 
-static const uint32_t g_code_view_to_lldb_registers_x86[] = {
-    LLDB_INVALID_REGNUM, // NONE
-    lldb_al_i386,        // AL
-    lldb_cl_i386,        // CL
-    lldb_dl_i386,        // DL
-    lldb_bl_i386,        // BL
-    lldb_ah_i386,        // AH
-    lldb_ch_i386,        // CH
-    lldb_dh_i386,        // DH
-    lldb_bh_i386,        // BH
-    lldb_ax_i386,        // AX
-    lldb_cx_i386,        // CX
-    lldb_dx_i386,        // DX
-    lldb_bx_i386,        // BX
-    lldb_sp_i386,        // SP
-    lldb_bp_i386,        // BP
-    lldb_si_i386,        // SI
-    lldb_di_i386,        // DI
-    lldb_eax_i386,       // EAX
-    lldb_ecx_i386,       // ECX
-    lldb_edx_i386,       // EDX
-    lldb_ebx_i386,       // EBX
-    lldb_esp_i386,       // ESP
-    lldb_ebp_i386,       // EBP
-    lldb_esi_i386,       // ESI
-    lldb_edi_i386,       // EDI
-    lldb_es_i386,        // ES
-    lldb_cs_i386,        // CS
-    lldb_ss_i386,        // SS
-    lldb_ds_i386,        // DS
-    lldb_fs_i386,        // FS
-    lldb_gs_i386,        // GS
-    LLDB_INVALID_REGNUM, // IP
-    LLDB_INVALID_REGNUM, // FLAGS
-    lldb_eip_i386,       // EIP
-    lldb_eflags_i386,    // EFLAGS
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, // TEMP
-    LLDB_INVALID_REGNUM, // TEMPH
-    LLDB_INVALID_REGNUM, // QUOTE
-    LLDB_INVALID_REGNUM, // PCDR3
-    LLDB_INVALID_REGNUM, // PCDR4
-    LLDB_INVALID_REGNUM, // PCDR5
-    LLDB_INVALID_REGNUM, // PCDR6
-    LLDB_INVALID_REGNUM, // PCDR7
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, // CR0
-    LLDB_INVALID_REGNUM, // CR1
-    LLDB_INVALID_REGNUM, // CR2
-    LLDB_INVALID_REGNUM, // CR3
-    LLDB_INVALID_REGNUM, // CR4
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    lldb_dr0_i386, // DR0
-    lldb_dr1_i386, // DR1
-    lldb_dr2_i386, // DR2
-    lldb_dr3_i386, // DR3
-    lldb_dr4_i386, // DR4
-    lldb_dr5_i386, // DR5
-    lldb_dr6_i386, // DR6
-    lldb_dr7_i386, // DR7
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, // GDTR
-    LLDB_INVALID_REGNUM, // GDTL
-    LLDB_INVALID_REGNUM, // IDTR
-    LLDB_INVALID_REGNUM, // IDTL
-    LLDB_INVALID_REGNUM, // LDTR
-    LLDB_INVALID_REGNUM, // TR
-    LLDB_INVALID_REGNUM, // PSEUDO1
-    LLDB_INVALID_REGNUM, // PSEUDO2
-    LLDB_INVALID_REGNUM, // PSEUDO3
-    LLDB_INVALID_REGNUM, // PSEUDO4
-    LLDB_INVALID_REGNUM, // PSEUDO5
-    LLDB_INVALID_REGNUM, // PSEUDO6
-    LLDB_INVALID_REGNUM, // PSEUDO7
-    LLDB_INVALID_REGNUM, // PSEUDO8
-    LLDB_INVALID_REGNUM, // PSEUDO9
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    lldb_st0_i386,       // ST0
-    lldb_st1_i386,       // ST1
-    lldb_st2_i386,       // ST2
-    lldb_st3_i386,       // ST3
-    lldb_st4_i386,       // ST4
-    lldb_st5_i386,       // ST5
-    lldb_st6_i386,       // ST6
-    lldb_st7_i386,       // ST7
-    LLDB_INVALID_REGNUM, // CTRL
-    LLDB_INVALID_REGNUM, // STAT
-    LLDB_INVALID_REGNUM, // TAG
-    LLDB_INVALID_REGNUM, // FPIP
-    LLDB_INVALID_REGNUM, // FPCS
-    LLDB_INVALID_REGNUM, // FPDO
-    LLDB_INVALID_REGNUM, // FPDS
-    LLDB_INVALID_REGNUM, // ISEM
-    LLDB_INVALID_REGNUM, // FPEIP
-    LLDB_INVALID_REGNUM, // FPEDO
-    lldb_mm0_i386,       // MM0
-    lldb_mm1_i386,       // MM1
-    lldb_mm2_i386,       // MM2
-    lldb_mm3_i386,       // MM3
-    lldb_mm4_i386,       // MM4
-    lldb_mm5_i386,       // MM5
-    lldb_mm6_i386,       // MM6
-    lldb_mm7_i386,       // MM7
-    lldb_xmm0_i386,      // XMM0
-    lldb_xmm1_i386,      // XMM1
-    lldb_xmm2_i386,      // XMM2
-    lldb_xmm3_i386,      // XMM3
-    lldb_xmm4_i386,      // XMM4
-    lldb_xmm5_i386,      // XMM5
-    lldb_xmm6_i386,      // XMM6
-    lldb_xmm7_i386       // XMM7
-};
-
-static const uint32_t g_code_view_to_lldb_registers_x86_64[] = {
-    LLDB_INVALID_REGNUM, // NONE
-    lldb_al_x86_64,      // AL
-    lldb_cl_x86_64,      // CL
-    lldb_dl_x86_64,      // DL
-    lldb_bl_x86_64,      // BL
-    lldb_ah_x86_64,      // AH
-    lldb_ch_x86_64,      // CH
-    lldb_dh_x86_64,      // DH
-    lldb_bh_x86_64,      // BH
-    lldb_ax_x86_64,      // AX
-    lldb_cx_x86_64,      // CX
-    lldb_dx_x86_64,      // DX
-    lldb_bx_x86_64,      // BX
-    lldb_sp_x86_64,      // SP
-    lldb_bp_x86_64,      // BP
-    lldb_si_x86_64,      // SI
-    lldb_di_x86_64,      // DI
-    lldb_eax_x86_64,     // EAX
-    lldb_ecx_x86_64,     // ECX
-    lldb_edx_x86_64,     // EDX
-    lldb_ebx_x86_64,     // EBX
-    lldb_esp_x86_64,     // ESP
-    lldb_ebp_x86_64,     // EBP
-    lldb_esi_x86_64,     // ESI
-    lldb_edi_x86_64,     // EDI
-    lldb_es_x86_64,      // ES
-    lldb_cs_x86_64,      // CS
-    lldb_ss_x86_64,      // SS
-    lldb_ds_x86_64,      // DS
-    lldb_fs_x86_64,      // FS
-    lldb_gs_x86_64,      // GS
-    LLDB_INVALID_REGNUM, // IP
-    LLDB_INVALID_REGNUM, // FLAGS
-    LLDB_INVALID_REGNUM, // EIP
-    LLDB_INVALID_REGNUM, // EFLAGS
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, // TEMP
-    LLDB_INVALID_REGNUM, // TEMPH
-    LLDB_INVALID_REGNUM, // QUOTE
-    LLDB_INVALID_REGNUM, // PCDR3
-    LLDB_INVALID_REGNUM, // PCDR4
-    LLDB_INVALID_REGNUM, // PCDR5
-    LLDB_INVALID_REGNUM, // PCDR6
-    LLDB_INVALID_REGNUM, // PCDR7
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, // CR0
-    LLDB_INVALID_REGNUM, // CR1
-    LLDB_INVALID_REGNUM, // CR2
-    LLDB_INVALID_REGNUM, // CR3
-    LLDB_INVALID_REGNUM, // CR4
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    lldb_dr0_x86_64, // DR0
-    lldb_dr1_x86_64, // DR1
-    lldb_dr2_x86_64, // DR2
-    lldb_dr3_x86_64, // DR3
-    lldb_dr4_x86_64, // DR4
-    lldb_dr5_x86_64, // DR5
-    lldb_dr6_x86_64, // DR6
-    lldb_dr7_x86_64, // DR7
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, // GDTR
-    LLDB_INVALID_REGNUM, // GDTL
-    LLDB_INVALID_REGNUM, // IDTR
-    LLDB_INVALID_REGNUM, // IDTL
-    LLDB_INVALID_REGNUM, // LDTR
-    LLDB_INVALID_REGNUM, // TR
-    LLDB_INVALID_REGNUM, // PSEUDO1
-    LLDB_INVALID_REGNUM, // PSEUDO2
-    LLDB_INVALID_REGNUM, // PSEUDO3
-    LLDB_INVALID_REGNUM, // PSEUDO4
-    LLDB_INVALID_REGNUM, // PSEUDO5
-    LLDB_INVALID_REGNUM, // PSEUDO6
-    LLDB_INVALID_REGNUM, // PSEUDO7
-    LLDB_INVALID_REGNUM, // PSEUDO8
-    LLDB_INVALID_REGNUM, // PSEUDO9
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    lldb_st0_x86_64,     // ST0
-    lldb_st1_x86_64,     // ST1
-    lldb_st2_x86_64,     // ST2
-    lldb_st3_x86_64,     // ST3
-    lldb_st4_x86_64,     // ST4
-    lldb_st5_x86_64,     // ST5
-    lldb_st6_x86_64,     // ST6
-    lldb_st7_x86_64,     // ST7
-    LLDB_INVALID_REGNUM, // CTRL
-    LLDB_INVALID_REGNUM, // STAT
-    LLDB_INVALID_REGNUM, // TAG
-    LLDB_INVALID_REGNUM, // FPIP
-    LLDB_INVALID_REGNUM, // FPCS
-    LLDB_INVALID_REGNUM, // FPDO
-    LLDB_INVALID_REGNUM, // FPDS
-    LLDB_INVALID_REGNUM, // ISEM
-    LLDB_INVALID_REGNUM, // FPEIP
-    LLDB_INVALID_REGNUM, // FPEDO
-    lldb_mm0_x86_64,     // MM0
-    lldb_mm1_x86_64,     // MM1
-    lldb_mm2_x86_64,     // MM2
-    lldb_mm3_x86_64,     // MM3
-    lldb_mm4_x86_64,     // MM4
-    lldb_mm5_x86_64,     // MM5
-    lldb_mm6_x86_64,     // MM6
-    lldb_mm7_x86_64,     // MM7
-    lldb_xmm0_x86_64,    // XMM0
-    lldb_xmm1_x86_64,    // XMM1
-    lldb_xmm2_x86_64,    // XMM2
-    lldb_xmm3_x86_64,    // XMM3
-    lldb_xmm4_x86_64,    // XMM4
-    lldb_xmm5_x86_64,    // XMM5
-    lldb_xmm6_x86_64,    // XMM6
-    lldb_xmm7_x86_64,    // XMM7
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM,
-    lldb_mxcsr_x86_64,   // MXCSR
-    LLDB_INVALID_REGNUM, // EDXEAX
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, // EMM0L
-    LLDB_INVALID_REGNUM, // EMM1L
-    LLDB_INVALID_REGNUM, // EMM2L
-    LLDB_INVALID_REGNUM, // EMM3L
-    LLDB_INVALID_REGNUM, // EMM4L
-    LLDB_INVALID_REGNUM, // EMM5L
-    LLDB_INVALID_REGNUM, // EMM6L
-    LLDB_INVALID_REGNUM, // EMM7L
-    LLDB_INVALID_REGNUM, // EMM0H
-    LLDB_INVALID_REGNUM, // EMM1H
-    LLDB_INVALID_REGNUM, // EMM2H
-    LLDB_INVALID_REGNUM, // EMM3H
-    LLDB_INVALID_REGNUM, // EMM4H
-    LLDB_INVALID_REGNUM, // EMM5H
-    LLDB_INVALID_REGNUM, // EMM6H
-    LLDB_INVALID_REGNUM, // EMM7H
-    LLDB_INVALID_REGNUM, // MM00
-    LLDB_INVALID_REGNUM, // MM01
-    LLDB_INVALID_REGNUM, // MM10
-    LLDB_INVALID_REGNUM, // MM11
-    LLDB_INVALID_REGNUM, // MM20
-    LLDB_INVALID_REGNUM, // MM21
-    LLDB_INVALID_REGNUM, // MM30
-    LLDB_INVALID_REGNUM, // MM31
-    LLDB_INVALID_REGNUM, // MM40
-    LLDB_INVALID_REGNUM, // MM41
-    LLDB_INVALID_REGNUM, // MM50
-    LLDB_INVALID_REGNUM, // MM51
-    LLDB_INVALID_REGNUM, // MM60
-    LLDB_INVALID_REGNUM, // MM61
-    LLDB_INVALID_REGNUM, // MM70
-    LLDB_INVALID_REGNUM, // MM71
-    lldb_xmm8_x86_64,    // XMM8
-    lldb_xmm9_x86_64,    // XMM9
-    lldb_xmm10_x86_64,   // XMM10
-    lldb_xmm11_x86_64,   // XMM11
-    lldb_xmm12_x86_64,   // XMM12
-    lldb_xmm13_x86_64,   // XMM13
-    lldb_xmm14_x86_64,   // XMM14
-    lldb_xmm15_x86_64,   // XMM15
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM,
-    lldb_sil_x86_64,   // SIL
-    lldb_dil_x86_64,   // DIL
-    lldb_bpl_x86_64,   // BPL
-    lldb_spl_x86_64,   // SPL
-    lldb_rax_x86_64,   // RAX
-    lldb_rbx_x86_64,   // RBX
-    lldb_rcx_x86_64,   // RCX
-    lldb_rdx_x86_64,   // RDX
-    lldb_rsi_x86_64,   // RSI
-    lldb_rdi_x86_64,   // RDI
-    lldb_rbp_x86_64,   // RBP
-    lldb_rsp_x86_64,   // RSP
-    lldb_r8_x86_64,    // R8
-    lldb_r9_x86_64,    // R9
-    lldb_r10_x86_64,   // R10
-    lldb_r11_x86_64,   // R11
-    lldb_r12_x86_64,   // R12
-    lldb_r13_x86_64,   // R13
-    lldb_r14_x86_64,   // R14
-    lldb_r15_x86_64,   // R15
-    lldb_r8l_x86_64,   // R8B
-    lldb_r9l_x86_64,   // R9B
-    lldb_r10l_x86_64,  // R10B
-    lldb_r11l_x86_64,  // R11B
-    lldb_r12l_x86_64,  // R12B
-    lldb_r13l_x86_64,  // R13B
-    lldb_r14l_x86_64,  // R14B
-    lldb_r15l_x86_64,  // R15B
-    lldb_r8w_x86_64,   // R8W
-    lldb_r9w_x86_64,   // R9W
-    lldb_r10w_x86_64,  // R10W
-    lldb_r11w_x86_64,  // R11W
-    lldb_r12w_x86_64,  // R12W
-    lldb_r13w_x86_64,  // R13W
-    lldb_r14w_x86_64,  // R14W
-    lldb_r15w_x86_64,  // R15W
-    lldb_r8d_x86_64,   // R8D
-    lldb_r9d_x86_64,   // R9D
-    lldb_r10d_x86_64,  // R10D
-    lldb_r11d_x86_64,  // R11D
-    lldb_r12d_x86_64,  // R12D
-    lldb_r13d_x86_64,  // R13D
-    lldb_r14d_x86_64,  // R14D
-    lldb_r15d_x86_64,  // R15D
-    lldb_ymm0_x86_64,  // AMD64_YMM0
-    lldb_ymm1_x86_64,  // AMD64_YMM1
-    lldb_ymm2_x86_64,  // AMD64_YMM2
-    lldb_ymm3_x86_64,  // AMD64_YMM3
-    lldb_ymm4_x86_64,  // AMD64_YMM4
-    lldb_ymm5_x86_64,  // AMD64_YMM5
-    lldb_ymm6_x86_64,  // AMD64_YMM6
-    lldb_ymm7_x86_64,  // AMD64_YMM7
-    lldb_ymm8_x86_64,  // AMD64_YMM8
-    lldb_ymm9_x86_64,  // AMD64_YMM9
-    lldb_ymm10_x86_64, // AMD64_YMM10
-    lldb_ymm11_x86_64, // AMD64_YMM11
-    lldb_ymm12_x86_64, // AMD64_YMM12
-    lldb_ymm13_x86_64, // AMD64_YMM13
-    lldb_ymm14_x86_64, // AMD64_YMM14
-    lldb_ymm15_x86_64, // AMD64_YMM15
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
-    lldb_bnd0_x86_64, // BND0
-    lldb_bnd1_x86_64, // BND1
-    lldb_bnd2_x86_64  // BND2
-};
-
-uint32_t GetLLDBRegisterNumber(llvm::Triple::ArchType arch_type,
-                               llvm::codeview::RegisterId register_id) {
-  switch (arch_type) {
-  case llvm::Triple::x86:
-    if (static_cast<uint16_t>(register_id) <
-        sizeof(g_code_view_to_lldb_registers_x86) /
-            sizeof(g_code_view_to_lldb_registers_x86[0]))
-      return g_code_view_to_lldb_registers_x86[static_cast<uint16_t>(
-          register_id)];
-
-    switch (register_id) {
-    case llvm::codeview::RegisterId::MXCSR:
-      return lldb_mxcsr_i386;
-    case llvm::codeview::RegisterId::BND0:
-      return lldb_bnd0_i386;
-    case llvm::codeview::RegisterId::BND1:
-      return lldb_bnd1_i386;
-    case llvm::codeview::RegisterId::BND2:
-      return lldb_bnd2_i386;
-    default:
-      return LLDB_INVALID_REGNUM;
-    }
-  case llvm::Triple::x86_64:
-    if (static_cast<uint16_t>(register_id) <
-        sizeof(g_code_view_to_lldb_registers_x86_64) /
-            sizeof(g_code_view_to_lldb_registers_x86_64[0]))
-      return g_code_view_to_lldb_registers_x86_64[static_cast<uint16_t>(
-          register_id)];
-
-    return LLDB_INVALID_REGNUM;
-  default:
-    return LLDB_INVALID_REGNUM;
-  }
-}
-
 uint32_t GetGenericRegisterNumber(llvm::codeview::RegisterId register_id) {
   if (register_id == llvm::codeview::RegisterId::VFRAME)
     return LLDB_REGNUM_GENERIC_FP;
@@ -610,6 +169,33 @@
   return MakeRegisterBasedLocationExpressionInternal(reg, offset, module);
 }
 
+static bool EmitVFrameEvaluationDWARFExpression(
+    llvm::StringRef program, llvm::Triple::ArchType arch_type, Stream &stream) {
+  // VFrame value always stored in $TO pseudo-register
+  return TranslateFPOProgramToDWARFExpression(program, "$T0", arch_type,
+                                              stream);
+}
+
+DWARFExpression lldb_private::npdb::MakeVFrameRelLocationExpression(
+    llvm::StringRef fpo_program, int32_t offset, lldb::ModuleSP module) {
+  return MakeLocationExpressionInternal(
+      module, [&](Stream &stream, RegisterKind &register_kind) -> bool {
+        const ArchSpec &architecture = module->GetArchitecture();
+
+        if (!EmitVFrameEvaluationDWARFExpression(fpo_program, architecture.GetMachine(),
+                                                 stream))
+          return false;
+
+        stream.PutHex8(llvm::dwarf::DW_OP_consts);
+        stream.PutSLEB128(offset);
+        stream.PutHex8(llvm::dwarf::DW_OP_plus);
+
+        register_kind = eRegisterKindLLDB;
+
+        return true;
+      });
+}
+
 DWARFExpression lldb_private::npdb::MakeGlobalLocationExpression(
     uint16_t section, uint32_t offset, ModuleSP module) {
   assert(section > 0);
Index: source/Plugins/SymbolFile/NativePDB/CodeViewRegisterMapping.h
===================================================================
--- /dev/null
+++ source/Plugins/SymbolFile/NativePDB/CodeViewRegisterMapping.h
@@ -0,0 +1,19 @@
+//===-- CodeViewRegisterMapping.h -------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef lldb_Plugins_SymbolFile_PDB_CodeViewRegisterMapping_h_
+#define lldb_Plugins_SymbolFile_PDB_CodeViewRegisterMapping_h_
+
+#include "llvm/ADT/Triple.h"
+#include "llvm/DebugInfo/CodeView/CodeView.h"
+
+uint32_t GetLLDBRegisterNumber(llvm::Triple::ArchType arch_type,
+                               llvm::codeview::RegisterId register_id);
+
+#endif
Index: source/Plugins/SymbolFile/NativePDB/CodeViewRegisterMapping.cpp
===================================================================
--- /dev/null
+++ source/Plugins/SymbolFile/NativePDB/CodeViewRegisterMapping.cpp
@@ -0,0 +1,458 @@
+//===-- CodeViewRegisterMapping.cpp -----------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CodeViewRegisterMapping.h"
+
+#include "lldb/lldb-defines.h"
+
+#include "Plugins/Process/Utility/lldb-x86-register-enums.h"
+
+using namespace lldb_private;
+
+static const uint32_t g_code_view_to_lldb_registers_x86[] = {
+    LLDB_INVALID_REGNUM, // NONE
+    lldb_al_i386,        // AL
+    lldb_cl_i386,        // CL
+    lldb_dl_i386,        // DL
+    lldb_bl_i386,        // BL
+    lldb_ah_i386,        // AH
+    lldb_ch_i386,        // CH
+    lldb_dh_i386,        // DH
+    lldb_bh_i386,        // BH
+    lldb_ax_i386,        // AX
+    lldb_cx_i386,        // CX
+    lldb_dx_i386,        // DX
+    lldb_bx_i386,        // BX
+    lldb_sp_i386,        // SP
+    lldb_bp_i386,        // BP
+    lldb_si_i386,        // SI
+    lldb_di_i386,        // DI
+    lldb_eax_i386,       // EAX
+    lldb_ecx_i386,       // ECX
+    lldb_edx_i386,       // EDX
+    lldb_ebx_i386,       // EBX
+    lldb_esp_i386,       // ESP
+    lldb_ebp_i386,       // EBP
+    lldb_esi_i386,       // ESI
+    lldb_edi_i386,       // EDI
+    lldb_es_i386,        // ES
+    lldb_cs_i386,        // CS
+    lldb_ss_i386,        // SS
+    lldb_ds_i386,        // DS
+    lldb_fs_i386,        // FS
+    lldb_gs_i386,        // GS
+    LLDB_INVALID_REGNUM, // IP
+    LLDB_INVALID_REGNUM, // FLAGS
+    lldb_eip_i386,       // EIP
+    lldb_eflags_i386,    // EFLAGS
+    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+    LLDB_INVALID_REGNUM, // TEMP
+    LLDB_INVALID_REGNUM, // TEMPH
+    LLDB_INVALID_REGNUM, // QUOTE
+    LLDB_INVALID_REGNUM, // PCDR3
+    LLDB_INVALID_REGNUM, // PCDR4
+    LLDB_INVALID_REGNUM, // PCDR5
+    LLDB_INVALID_REGNUM, // PCDR6
+    LLDB_INVALID_REGNUM, // PCDR7
+    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+    LLDB_INVALID_REGNUM, // CR0
+    LLDB_INVALID_REGNUM, // CR1
+    LLDB_INVALID_REGNUM, // CR2
+    LLDB_INVALID_REGNUM, // CR3
+    LLDB_INVALID_REGNUM, // CR4
+    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+    lldb_dr0_i386, // DR0
+    lldb_dr1_i386, // DR1
+    lldb_dr2_i386, // DR2
+    lldb_dr3_i386, // DR3
+    lldb_dr4_i386, // DR4
+    lldb_dr5_i386, // DR5
+    lldb_dr6_i386, // DR6
+    lldb_dr7_i386, // DR7
+    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+    LLDB_INVALID_REGNUM, // GDTR
+    LLDB_INVALID_REGNUM, // GDTL
+    LLDB_INVALID_REGNUM, // IDTR
+    LLDB_INVALID_REGNUM, // IDTL
+    LLDB_INVALID_REGNUM, // LDTR
+    LLDB_INVALID_REGNUM, // TR
+    LLDB_INVALID_REGNUM, // PSEUDO1
+    LLDB_INVALID_REGNUM, // PSEUDO2
+    LLDB_INVALID_REGNUM, // PSEUDO3
+    LLDB_INVALID_REGNUM, // PSEUDO4
+    LLDB_INVALID_REGNUM, // PSEUDO5
+    LLDB_INVALID_REGNUM, // PSEUDO6
+    LLDB_INVALID_REGNUM, // PSEUDO7
+    LLDB_INVALID_REGNUM, // PSEUDO8
+    LLDB_INVALID_REGNUM, // PSEUDO9
+    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+    lldb_st0_i386,       // ST0
+    lldb_st1_i386,       // ST1
+    lldb_st2_i386,       // ST2
+    lldb_st3_i386,       // ST3
+    lldb_st4_i386,       // ST4
+    lldb_st5_i386,       // ST5
+    lldb_st6_i386,       // ST6
+    lldb_st7_i386,       // ST7
+    LLDB_INVALID_REGNUM, // CTRL
+    LLDB_INVALID_REGNUM, // STAT
+    LLDB_INVALID_REGNUM, // TAG
+    LLDB_INVALID_REGNUM, // FPIP
+    LLDB_INVALID_REGNUM, // FPCS
+    LLDB_INVALID_REGNUM, // FPDO
+    LLDB_INVALID_REGNUM, // FPDS
+    LLDB_INVALID_REGNUM, // ISEM
+    LLDB_INVALID_REGNUM, // FPEIP
+    LLDB_INVALID_REGNUM, // FPEDO
+    lldb_mm0_i386,       // MM0
+    lldb_mm1_i386,       // MM1
+    lldb_mm2_i386,       // MM2
+    lldb_mm3_i386,       // MM3
+    lldb_mm4_i386,       // MM4
+    lldb_mm5_i386,       // MM5
+    lldb_mm6_i386,       // MM6
+    lldb_mm7_i386,       // MM7
+    lldb_xmm0_i386,      // XMM0
+    lldb_xmm1_i386,      // XMM1
+    lldb_xmm2_i386,      // XMM2
+    lldb_xmm3_i386,      // XMM3
+    lldb_xmm4_i386,      // XMM4
+    lldb_xmm5_i386,      // XMM5
+    lldb_xmm6_i386,      // XMM6
+    lldb_xmm7_i386       // XMM7
+};
+
+static const uint32_t g_code_view_to_lldb_registers_x86_64[] = {
+    LLDB_INVALID_REGNUM, // NONE
+    lldb_al_x86_64,      // AL
+    lldb_cl_x86_64,      // CL
+    lldb_dl_x86_64,      // DL
+    lldb_bl_x86_64,      // BL
+    lldb_ah_x86_64,      // AH
+    lldb_ch_x86_64,      // CH
+    lldb_dh_x86_64,      // DH
+    lldb_bh_x86_64,      // BH
+    lldb_ax_x86_64,      // AX
+    lldb_cx_x86_64,      // CX
+    lldb_dx_x86_64,      // DX
+    lldb_bx_x86_64,      // BX
+    lldb_sp_x86_64,      // SP
+    lldb_bp_x86_64,      // BP
+    lldb_si_x86_64,      // SI
+    lldb_di_x86_64,      // DI
+    lldb_eax_x86_64,     // EAX
+    lldb_ecx_x86_64,     // ECX
+    lldb_edx_x86_64,     // EDX
+    lldb_ebx_x86_64,     // EBX
+    lldb_esp_x86_64,     // ESP
+    lldb_ebp_x86_64,     // EBP
+    lldb_esi_x86_64,     // ESI
+    lldb_edi_x86_64,     // EDI
+    lldb_es_x86_64,      // ES
+    lldb_cs_x86_64,      // CS
+    lldb_ss_x86_64,      // SS
+    lldb_ds_x86_64,      // DS
+    lldb_fs_x86_64,      // FS
+    lldb_gs_x86_64,      // GS
+    LLDB_INVALID_REGNUM, // IP
+    LLDB_INVALID_REGNUM, // FLAGS
+    LLDB_INVALID_REGNUM, // EIP
+    LLDB_INVALID_REGNUM, // EFLAGS
+    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+    LLDB_INVALID_REGNUM, // TEMP
+    LLDB_INVALID_REGNUM, // TEMPH
+    LLDB_INVALID_REGNUM, // QUOTE
+    LLDB_INVALID_REGNUM, // PCDR3
+    LLDB_INVALID_REGNUM, // PCDR4
+    LLDB_INVALID_REGNUM, // PCDR5
+    LLDB_INVALID_REGNUM, // PCDR6
+    LLDB_INVALID_REGNUM, // PCDR7
+    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+    LLDB_INVALID_REGNUM, // CR0
+    LLDB_INVALID_REGNUM, // CR1
+    LLDB_INVALID_REGNUM, // CR2
+    LLDB_INVALID_REGNUM, // CR3
+    LLDB_INVALID_REGNUM, // CR4
+    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+    lldb_dr0_x86_64, // DR0
+    lldb_dr1_x86_64, // DR1
+    lldb_dr2_x86_64, // DR2
+    lldb_dr3_x86_64, // DR3
+    lldb_dr4_x86_64, // DR4
+    lldb_dr5_x86_64, // DR5
+    lldb_dr6_x86_64, // DR6
+    lldb_dr7_x86_64, // DR7
+    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+    LLDB_INVALID_REGNUM, // GDTR
+    LLDB_INVALID_REGNUM, // GDTL
+    LLDB_INVALID_REGNUM, // IDTR
+    LLDB_INVALID_REGNUM, // IDTL
+    LLDB_INVALID_REGNUM, // LDTR
+    LLDB_INVALID_REGNUM, // TR
+    LLDB_INVALID_REGNUM, // PSEUDO1
+    LLDB_INVALID_REGNUM, // PSEUDO2
+    LLDB_INVALID_REGNUM, // PSEUDO3
+    LLDB_INVALID_REGNUM, // PSEUDO4
+    LLDB_INVALID_REGNUM, // PSEUDO5
+    LLDB_INVALID_REGNUM, // PSEUDO6
+    LLDB_INVALID_REGNUM, // PSEUDO7
+    LLDB_INVALID_REGNUM, // PSEUDO8
+    LLDB_INVALID_REGNUM, // PSEUDO9
+    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+    lldb_st0_x86_64,     // ST0
+    lldb_st1_x86_64,     // ST1
+    lldb_st2_x86_64,     // ST2
+    lldb_st3_x86_64,     // ST3
+    lldb_st4_x86_64,     // ST4
+    lldb_st5_x86_64,     // ST5
+    lldb_st6_x86_64,     // ST6
+    lldb_st7_x86_64,     // ST7
+    LLDB_INVALID_REGNUM, // CTRL
+    LLDB_INVALID_REGNUM, // STAT
+    LLDB_INVALID_REGNUM, // TAG
+    LLDB_INVALID_REGNUM, // FPIP
+    LLDB_INVALID_REGNUM, // FPCS
+    LLDB_INVALID_REGNUM, // FPDO
+    LLDB_INVALID_REGNUM, // FPDS
+    LLDB_INVALID_REGNUM, // ISEM
+    LLDB_INVALID_REGNUM, // FPEIP
+    LLDB_INVALID_REGNUM, // FPEDO
+    lldb_mm0_x86_64,     // MM0
+    lldb_mm1_x86_64,     // MM1
+    lldb_mm2_x86_64,     // MM2
+    lldb_mm3_x86_64,     // MM3
+    lldb_mm4_x86_64,     // MM4
+    lldb_mm5_x86_64,     // MM5
+    lldb_mm6_x86_64,     // MM6
+    lldb_mm7_x86_64,     // MM7
+    lldb_xmm0_x86_64,    // XMM0
+    lldb_xmm1_x86_64,    // XMM1
+    lldb_xmm2_x86_64,    // XMM2
+    lldb_xmm3_x86_64,    // XMM3
+    lldb_xmm4_x86_64,    // XMM4
+    lldb_xmm5_x86_64,    // XMM5
+    lldb_xmm6_x86_64,    // XMM6
+    lldb_xmm7_x86_64,    // XMM7
+    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+    LLDB_INVALID_REGNUM,
+    lldb_mxcsr_x86_64,   // MXCSR
+    LLDB_INVALID_REGNUM, // EDXEAX
+    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+    LLDB_INVALID_REGNUM,
+    LLDB_INVALID_REGNUM, // EMM0L
+    LLDB_INVALID_REGNUM, // EMM1L
+    LLDB_INVALID_REGNUM, // EMM2L
+    LLDB_INVALID_REGNUM, // EMM3L
+    LLDB_INVALID_REGNUM, // EMM4L
+    LLDB_INVALID_REGNUM, // EMM5L
+    LLDB_INVALID_REGNUM, // EMM6L
+    LLDB_INVALID_REGNUM, // EMM7L
+    LLDB_INVALID_REGNUM, // EMM0H
+    LLDB_INVALID_REGNUM, // EMM1H
+    LLDB_INVALID_REGNUM, // EMM2H
+    LLDB_INVALID_REGNUM, // EMM3H
+    LLDB_INVALID_REGNUM, // EMM4H
+    LLDB_INVALID_REGNUM, // EMM5H
+    LLDB_INVALID_REGNUM, // EMM6H
+    LLDB_INVALID_REGNUM, // EMM7H
+    LLDB_INVALID_REGNUM, // MM00
+    LLDB_INVALID_REGNUM, // MM01
+    LLDB_INVALID_REGNUM, // MM10
+    LLDB_INVALID_REGNUM, // MM11
+    LLDB_INVALID_REGNUM, // MM20
+    LLDB_INVALID_REGNUM, // MM21
+    LLDB_INVALID_REGNUM, // MM30
+    LLDB_INVALID_REGNUM, // MM31
+    LLDB_INVALID_REGNUM, // MM40
+    LLDB_INVALID_REGNUM, // MM41
+    LLDB_INVALID_REGNUM, // MM50
+    LLDB_INVALID_REGNUM, // MM51
+    LLDB_INVALID_REGNUM, // MM60
+    LLDB_INVALID_REGNUM, // MM61
+    LLDB_INVALID_REGNUM, // MM70
+    LLDB_INVALID_REGNUM, // MM71
+    lldb_xmm8_x86_64,    // XMM8
+    lldb_xmm9_x86_64,    // XMM9
+    lldb_xmm10_x86_64,   // XMM10
+    lldb_xmm11_x86_64,   // XMM11
+    lldb_xmm12_x86_64,   // XMM12
+    lldb_xmm13_x86_64,   // XMM13
+    lldb_xmm14_x86_64,   // XMM14
+    lldb_xmm15_x86_64,   // XMM15
+    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+    LLDB_INVALID_REGNUM,
+    lldb_sil_x86_64,   // SIL
+    lldb_dil_x86_64,   // DIL
+    lldb_bpl_x86_64,   // BPL
+    lldb_spl_x86_64,   // SPL
+    lldb_rax_x86_64,   // RAX
+    lldb_rbx_x86_64,   // RBX
+    lldb_rcx_x86_64,   // RCX
+    lldb_rdx_x86_64,   // RDX
+    lldb_rsi_x86_64,   // RSI
+    lldb_rdi_x86_64,   // RDI
+    lldb_rbp_x86_64,   // RBP
+    lldb_rsp_x86_64,   // RSP
+    lldb_r8_x86_64,    // R8
+    lldb_r9_x86_64,    // R9
+    lldb_r10_x86_64,   // R10
+    lldb_r11_x86_64,   // R11
+    lldb_r12_x86_64,   // R12
+    lldb_r13_x86_64,   // R13
+    lldb_r14_x86_64,   // R14
+    lldb_r15_x86_64,   // R15
+    lldb_r8l_x86_64,   // R8B
+    lldb_r9l_x86_64,   // R9B
+    lldb_r10l_x86_64,  // R10B
+    lldb_r11l_x86_64,  // R11B
+    lldb_r12l_x86_64,  // R12B
+    lldb_r13l_x86_64,  // R13B
+    lldb_r14l_x86_64,  // R14B
+    lldb_r15l_x86_64,  // R15B
+    lldb_r8w_x86_64,   // R8W
+    lldb_r9w_x86_64,   // R9W
+    lldb_r10w_x86_64,  // R10W
+    lldb_r11w_x86_64,  // R11W
+    lldb_r12w_x86_64,  // R12W
+    lldb_r13w_x86_64,  // R13W
+    lldb_r14w_x86_64,  // R14W
+    lldb_r15w_x86_64,  // R15W
+    lldb_r8d_x86_64,   // R8D
+    lldb_r9d_x86_64,   // R9D
+    lldb_r10d_x86_64,  // R10D
+    lldb_r11d_x86_64,  // R11D
+    lldb_r12d_x86_64,  // R12D
+    lldb_r13d_x86_64,  // R13D
+    lldb_r14d_x86_64,  // R14D
+    lldb_r15d_x86_64,  // R15D
+    lldb_ymm0_x86_64,  // AMD64_YMM0
+    lldb_ymm1_x86_64,  // AMD64_YMM1
+    lldb_ymm2_x86_64,  // AMD64_YMM2
+    lldb_ymm3_x86_64,  // AMD64_YMM3
+    lldb_ymm4_x86_64,  // AMD64_YMM4
+    lldb_ymm5_x86_64,  // AMD64_YMM5
+    lldb_ymm6_x86_64,  // AMD64_YMM6
+    lldb_ymm7_x86_64,  // AMD64_YMM7
+    lldb_ymm8_x86_64,  // AMD64_YMM8
+    lldb_ymm9_x86_64,  // AMD64_YMM9
+    lldb_ymm10_x86_64, // AMD64_YMM10
+    lldb_ymm11_x86_64, // AMD64_YMM11
+    lldb_ymm12_x86_64, // AMD64_YMM12
+    lldb_ymm13_x86_64, // AMD64_YMM13
+    lldb_ymm14_x86_64, // AMD64_YMM14
+    lldb_ymm15_x86_64, // AMD64_YMM15
+    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+    lldb_bnd0_x86_64, // BND0
+    lldb_bnd1_x86_64, // BND1
+    lldb_bnd2_x86_64  // BND2
+};
+
+uint32_t GetLLDBRegisterNumber(llvm::Triple::ArchType arch_type,
+                               llvm::codeview::RegisterId register_id) {
+  switch (arch_type) {
+  case llvm::Triple::x86:
+    if (static_cast<uint16_t>(register_id) <
+        sizeof(g_code_view_to_lldb_registers_x86) /
+            sizeof(g_code_view_to_lldb_registers_x86[0]))
+      return g_code_view_to_lldb_registers_x86[static_cast<uint16_t>(
+          register_id)];
+
+    switch (register_id) {
+    case llvm::codeview::RegisterId::MXCSR:
+      return lldb_mxcsr_i386;
+    case llvm::codeview::RegisterId::BND0:
+      return lldb_bnd0_i386;
+    case llvm::codeview::RegisterId::BND1:
+      return lldb_bnd1_i386;
+    case llvm::codeview::RegisterId::BND2:
+      return lldb_bnd2_i386;
+    default:
+      return LLDB_INVALID_REGNUM;
+    }
+  case llvm::Triple::x86_64:
+    if (static_cast<uint16_t>(register_id) <
+        sizeof(g_code_view_to_lldb_registers_x86_64) /
+            sizeof(g_code_view_to_lldb_registers_x86_64[0]))
+      return g_code_view_to_lldb_registers_x86_64[static_cast<uint16_t>(
+          register_id)];
+
+    return LLDB_INVALID_REGNUM;
+  default:
+    return LLDB_INVALID_REGNUM;
+  }
+}
Index: source/Plugins/SymbolFile/NativePDB/CMakeLists.txt
===================================================================
--- source/Plugins/SymbolFile/NativePDB/CMakeLists.txt
+++ source/Plugins/SymbolFile/NativePDB/CMakeLists.txt
@@ -1,7 +1,9 @@
 add_lldb_library(lldbPluginSymbolFileNativePDB PLUGIN
+  CodeViewRegisterMapping.cpp
   CompileUnitIndex.cpp
   DWARFLocationExpression.cpp
   PdbAstBuilder.cpp
+  PdbFPOProgramToDWARFExpression.cpp
   PdbIndex.cpp
   PdbSymUid.cpp
   PdbUtil.cpp
@@ -13,7 +15,7 @@
     clangLex
     lldbCore
     lldbSymbol
-	  lldbUtility
+    lldbUtility
   LINK_COMPONENTS
     DebugInfoCodeView
     DebugInfoPDB
Index: source/Expression/DWARFExpression.cpp
===================================================================
--- source/Expression/DWARFExpression.cpp
+++ source/Expression/DWARFExpression.cpp
@@ -3204,7 +3204,7 @@
     break;
   default:
     s.Printf("UNKNOWN ONE-OPERAND OPCODE, #%u", opcode);
-    return true;
+    return false;
   }
 
   switch (size) {
@@ -3250,7 +3250,7 @@
     break;
   }
 
-  return false;
+  return true;
 }
 
 bool DWARFExpression::PrintDWARFExpression(Stream &s, const DataExtractor &data,
Index: lit/SymbolFile/PDB/variables-locations.test
===================================================================
--- lit/SymbolFile/PDB/variables-locations.test
+++ lit/SymbolFile/PDB/variables-locations.test
@@ -12,3 +12,8 @@
 
 CHECK: loc_0 = true
 CHECK: loc_1 = 3333
+
+CHECK: arg_0 = 22
+
+CHECK: loc_0 = (a = 1234)
+CHECK: loc_1 = 5678
Index: lit/SymbolFile/PDB/Inputs/VariablesLocationsTest.script
===================================================================
--- lit/SymbolFile/PDB/Inputs/VariablesLocationsTest.script
+++ lit/SymbolFile/PDB/Inputs/VariablesLocationsTest.script
@@ -1,4 +1,5 @@
 breakpoint set --file VariablesLocationsTest.cpp --line 6
+breakpoint set --file VariablesLocationsTest.cpp --line 15
 
 run
 
@@ -14,3 +15,11 @@
 
 frame variable loc_0
 frame variable loc_1
+
+continue
+
+frame variable arg_0
+
+frame variable loc_0
+frame variable loc_1
+
Index: lit/SymbolFile/PDB/Inputs/VariablesLocationsTest.cpp
===================================================================
--- lit/SymbolFile/PDB/Inputs/VariablesLocationsTest.cpp
+++ lit/SymbolFile/PDB/Inputs/VariablesLocationsTest.cpp
@@ -5,11 +5,22 @@
   double loc_1 = 0.5678;
 }
 
+__declspec(align(128)) struct S {
+  int a = 1234;
+};
+
+void bar(int arg_0) {
+ S loc_0;
+ int loc_1 = 5678;
+}
+
+
 int main(int argc, char *argv[]) {
   bool loc_0 = true;
   int loc_1 = 3333;
 
   foo(1111, 0.1234);
+  bar(22);
 
   return 0;
 }
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to