leonid.mashinskiy created this revision.
leonid.mashinskiy added reviewers: zturner, asmith, stella.stamenova, 
aleksandr.urakov.
leonid.mashinskiy added a project: LLDB.
Herald added subscribers: lldb-commits, JDevlieghere, aprantl, mgorny.

This patch makes LLDB able to retrieve proper values for function arguments and 
local variables stored in PDB relative to VFRAME register.

Patch contains retrieval of corresponding FPO table entries from PDB and a 
generic translator from FPO programs to DWARF expressions to get correct VFRAME 
value.

Patch also improves variables-locations.test and makes this test passable on 
x86.

Related to D53086 <https://reviews.llvm.org/D53086>


Repository:
  rLLDB LLDB

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/Plugins/SymbolFile/PDB/CMakeLists.txt
  source/Plugins/SymbolFile/PDB/CodeViewRegisterMapping.cpp
  source/Plugins/SymbolFile/PDB/CodeViewRegisterMapping.h
  source/Plugins/SymbolFile/PDB/PDBFPOProgramToDWARFExpression.cpp
  source/Plugins/SymbolFile/PDB/PDBFPOProgramToDWARFExpression.h
  source/Plugins/SymbolFile/PDB/PDBLocationToDWARFExpression.cpp
  source/Plugins/SymbolFile/PDB/PDBLocationToDWARFExpression.h
  source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp

Index: source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp
===================================================================
--- source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp
+++ source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp
@@ -951,12 +951,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());
+      }
     }
   }
 
@@ -969,7 +982,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
@@ -8,488 +8,63 @@
 //===----------------------------------------------------------------------===//
 
 #include "PDBLocationToDWARFExpression.h"
+#include "CodeViewRegisterMapping.h"
+#include "PDBFPOProgramToDWARFExpression.h"
 
 #include "lldb/Core/Section.h"
 #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"
-
 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 +106,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 +147,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/PDBFPOProgramToDWARFExpression.h
===================================================================
--- /dev/null
+++ source/Plugins/SymbolFile/PDB/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/PDB/PDBFPOProgramToDWARFExpression.cpp
===================================================================
--- /dev/null
+++ source/Plugins/SymbolFile/PDB/PDBFPOProgramToDWARFExpression.cpp
@@ -0,0 +1,487 @@
+//===-- 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/StringExtras.h"
+#include "llvm/DebugInfo/CodeView/CodeView.h"
+#include "llvm/DebugInfo/CodeView/EnumTables.h"
+
+#include <map>
+
+using namespace lldb;
+using namespace lldb_private;
+
+namespace {
+
+class FPOProgramNode;
+using FPOProgramNodePtr = std::shared_ptr<FPOProgramNode>;
+class FPOProgramASTVisitor;
+
+class FPOProgramNode : std::enable_shared_from_this<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, FPOProgramNodePtr left,
+                         FPOProgramNodePtr right)
+      : FPOProgramNode(BinaryOp), m_op_type(op_type), m_left(std::move(left)),
+        m_right(std::move(right)) {}
+
+  void Accept(FPOProgramASTVisitor *visitor) override;
+
+  OpType GetOpType() const { return m_op_type; }
+
+  const FPOProgramNodePtr &Left() const { return m_left; }
+  FPOProgramNodePtr &Left() { return m_left; }
+
+  const FPOProgramNodePtr &Right() const { return m_right; }
+  FPOProgramNodePtr &Right() { return m_right; }
+
+private:
+  OpType m_op_type;
+  FPOProgramNodePtr m_left;
+  FPOProgramNodePtr m_right;
+};
+
+class FPOProgramNodeUnaryOp : public FPOProgramNode {
+public:
+  enum OpType {
+    Deref,
+  };
+
+  FPOProgramNodeUnaryOp(OpType op_type, FPOProgramNodePtr operand)
+      : FPOProgramNode(UnaryOp), m_op_type(op_type),
+        m_operand(std::move(operand)) {}
+
+  void Accept(FPOProgramASTVisitor *visitor) override;
+
+  OpType GetOpType() const { return m_op_type; }
+
+  const FPOProgramNodePtr &Operand() const { return m_operand; }
+  FPOProgramNodePtr &Operand() { return m_operand; }
+
+private:
+  OpType m_op_type;
+  FPOProgramNodePtr 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 std::map<llvm::StringRef, FPOProgramNodePtr> &dependent_programs)
+      : m_dependent_programs(dependent_programs) {}
+
+  void Merge(FPOProgramNodePtr &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(FPOProgramNodePtr &node_ref) const;
+
+private:
+  const std::map<llvm::StringRef, FPOProgramNodePtr> &m_dependent_programs;
+};
+
+void FPOProgramASTVisitorMergeDependent::Merge(FPOProgramNodePtr &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(
+    FPOProgramNodePtr &node_ref) const {
+  if (node_ref->GetKind() != FPOProgramNode::Register) {
+    return;
+  }
+
+  auto *node_register_ref =
+      static_cast<FPOProgramNodeRegisterRef *>(node_ref.get());
+
+  auto it = m_dependent_programs.find(node_register_ref->GetName());
+  if (it == m_dependent_programs.end()) {
+    return;
+  }
+
+  node_ref = it->second;
+}
+
+class FPOProgramASTVisitorResolveRegisterRefs : public FPOProgramASTVisitor {
+public:
+  FPOProgramASTVisitorResolveRegisterRefs(llvm::Triple::ArchType arch_type)
+      : m_arch_type(arch_type) {}
+
+  bool Resolve(const FPOProgramNodePtr &program);
+
+private:
+  void Visit(FPOProgramNodeRegisterRef *node) override;
+  void Visit(FPOProgramNodeIntegerLiteral *node) override {}
+  void Visit(FPOProgramNodeBinaryOp *node) override;
+  void Visit(FPOProgramNodeUnaryOp *node) override;
+
+private:
+  llvm::Triple::ArchType m_arch_type;
+  bool m_no_error_flag = false;
+};
+
+bool FPOProgramASTVisitorResolveRegisterRefs::Resolve(
+    const FPOProgramNodePtr &program) {
+  program->Accept(this);
+  return m_no_error_flag;
+}
+
+void FPOProgramASTVisitorResolveRegisterRefs::Visit(
+    FPOProgramNodeRegisterRef *node) {
+  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(const FPOProgramNodePtr &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(const FPOProgramNodePtr &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;
+  default:
+    llvm_unreachable("Invalid binary operation");
+  }
+}
+
+void FPOProgramASTVisitorDWARFCodegen::Visit(FPOProgramNodeUnaryOp *node) {
+  Emit(node->Operand());
+
+  switch (node->GetOpType()) {
+  case FPOProgramNodeUnaryOp::Deref:
+    m_out_stream.PutHex8(DW_OP_deref);
+    break;
+  default:
+    llvm_unreachable("Invalid unary operation");
+  }
+}
+} // namespace
+
+static bool ParseFPOSingleAssignmentProgram(llvm::StringRef program,
+                                            llvm::StringRef &register_name,
+                                            FPOProgramNodePtr &ast) {
+  llvm::SmallVector<llvm::StringRef, 16> tokens;
+  llvm::SplitString(program, tokens, " ");
+
+  if (tokens.empty())
+    return false;
+
+  llvm::SmallVector<FPOProgramNodePtr, 4> eval_stack;
+
+  std::map<llvm::StringRef, FPOProgramNodeBinaryOp::OpType> ops_binary = {
+      {"+", FPOProgramNodeBinaryOp::Plus},
+      {"-", FPOProgramNodeBinaryOp::Minus},
+      {"@", FPOProgramNodeBinaryOp::Align},
+  };
+
+  std::map<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
+      FPOProgramNodePtr &&right = eval_stack.pop_back_val();
+      FPOProgramNodePtr &&left = eval_stack.pop_back_val();
+      auto node = std::make_shared<FPOProgramNodeBinaryOp>(
+          ops_binary_it->second, std::move(left), std::move(right));
+      eval_stack.push_back(std::move(node));
+      continue;
+    }
+
+    auto ops_unary_it = ops_unary.find(cur);
+    if (ops_unary_it != ops_unary.end()) {
+      // token is unary operator
+      FPOProgramNodePtr &&operand = eval_stack.pop_back_val();
+      auto node = std::make_shared<FPOProgramNodeUnaryOp>(ops_unary_it->second,
+                                                          std::move(operand));
+      eval_stack.push_back(std::move(node));
+      continue;
+    }
+
+    if (cur.startswith("$")) {
+      // token is register ref
+      eval_stack.push_back(std::make_shared<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(
+          std::make_shared<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 FPOProgramNodePtr ParseFPOProgram(llvm::StringRef program,
+                                         llvm::StringRef register_name) {
+  FPOProgramNodePtr result;
+
+  llvm::SmallVector<llvm::StringRef, 6> assignment_programs;
+  llvm::SplitString(program.trim(), assignment_programs, "=");
+
+  std::map<llvm::StringRef, FPOProgramNodePtr> dependent_programs;
+
+  for (const llvm::StringRef &assignment_program : assignment_programs) {
+    llvm::StringRef lvalue_name;
+    FPOProgramNodePtr rvalue_ast;
+    if (!ParseFPOSingleAssignmentProgram(assignment_program, lvalue_name,
+                                         rvalue_ast)) {
+      return result;
+    }
+
+    if (lvalue_name == register_name) {
+      // found target assignment program - no need to parse further
+      result = std::move(rvalue_ast);
+      break;
+    }
+
+    dependent_programs[lvalue_name] = std::move(rvalue_ast);
+  }
+
+  // emplace dependent subtrees into target program
+  FPOProgramASTVisitorMergeDependent merger(dependent_programs);
+  merger.Merge(result);
+
+  return result;
+}
+
+bool TranslateFPOProgramToDWARFExpression(llvm::StringRef program,
+                                          llvm::StringRef register_name,
+                                          llvm::Triple::ArchType arch_type,
+                                          Stream &stream) {
+  FPOProgramNodePtr target_program = ParseFPOProgram(program, register_name);
+
+  FPOProgramASTVisitorResolveRegisterRefs resolver(arch_type);
+  if (!resolver.Resolve(target_program)) {
+    return false;
+  }
+
+  FPOProgramASTVisitorDWARFCodegen codegen(stream);
+  codegen.Emit(target_program);
+  return true;
+}
Index: source/Plugins/SymbolFile/PDB/CodeViewRegisterMapping.h
===================================================================
--- /dev/null
+++ source/Plugins/SymbolFile/PDB/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/PDB/CodeViewRegisterMapping.cpp
===================================================================
--- /dev/null
+++ source/Plugins/SymbolFile/PDB/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/PDB/CMakeLists.txt
===================================================================
--- source/Plugins/SymbolFile/PDB/CMakeLists.txt
+++ source/Plugins/SymbolFile/PDB/CMakeLists.txt
@@ -1,7 +1,9 @@
 add_lldb_library(lldbPluginSymbolFilePDB PLUGIN
   PDBASTParser.cpp
   PDBLocationToDWARFExpression.cpp
+  PDBFPOProgramToDWARFExpression.cpp
   SymbolFilePDB.cpp
+  CodeViewRegisterMapping.cpp
 
   LINK_LIBS
     clangAST
Index: lit/SymbolFile/PDB/variables-locations.test
===================================================================
--- lit/SymbolFile/PDB/variables-locations.test
+++ lit/SymbolFile/PDB/variables-locations.test
@@ -13,3 +13,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