[Lldb-commits] [lldb] r352845 - [PDB] Fix location retrieval for function local variables and arguments that are

Aleksandr Urakov via lldb-commits lldb-commits at lists.llvm.org
Fri Feb 1 02:01:19 PST 2019


Author: aleksandr.urakov
Date: Fri Feb  1 02:01:18 2019
New Revision: 352845

URL: http://llvm.org/viewvc/llvm-project?rev=352845&view=rev
Log:
[PDB] Fix location retrieval for function local variables and arguments that are
stored relative to VFRAME

Summary:
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.

Patch By: leonid.mashinsky

Reviewers: zturner, asmith, stella.stamenova, aleksandr.urakov

Reviewed By: zturner

Subscribers: arphaman, labath, mgorny, aprantl, JDevlieghere, lldb-commits

Tags: #lldb

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

Added:
    lldb/trunk/source/Plugins/SymbolFile/NativePDB/CodeViewRegisterMapping.cpp
      - copied, changed from r352780, lldb/trunk/source/Plugins/SymbolFile/PDB/PDBLocationToDWARFExpression.cpp
    lldb/trunk/source/Plugins/SymbolFile/NativePDB/CodeViewRegisterMapping.h
    lldb/trunk/source/Plugins/SymbolFile/NativePDB/PdbFPOProgramToDWARFExpression.cpp
    lldb/trunk/source/Plugins/SymbolFile/NativePDB/PdbFPOProgramToDWARFExpression.h
    lldb/trunk/unittests/SymbolFile/NativePDB/
    lldb/trunk/unittests/SymbolFile/NativePDB/CMakeLists.txt
    lldb/trunk/unittests/SymbolFile/NativePDB/PdbFPOProgramToDWARFExpressionTests.cpp
Modified:
    lldb/trunk/lit/SymbolFile/PDB/Inputs/VariablesLocationsTest.cpp
    lldb/trunk/lit/SymbolFile/PDB/Inputs/VariablesLocationsTest.script
    lldb/trunk/lit/SymbolFile/PDB/variables-locations.test
    lldb/trunk/source/Expression/DWARFExpression.cpp
    lldb/trunk/source/Plugins/SymbolFile/NativePDB/CMakeLists.txt
    lldb/trunk/source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.cpp
    lldb/trunk/source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.h
    lldb/trunk/source/Plugins/SymbolFile/NativePDB/PdbIndex.h
    lldb/trunk/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp
    lldb/trunk/source/Plugins/SymbolFile/NativePDB/PdbUtil.h
    lldb/trunk/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
    lldb/trunk/source/Plugins/SymbolFile/PDB/CMakeLists.txt
    lldb/trunk/source/Plugins/SymbolFile/PDB/PDBLocationToDWARFExpression.cpp
    lldb/trunk/source/Plugins/SymbolFile/PDB/PDBLocationToDWARFExpression.h
    lldb/trunk/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp
    lldb/trunk/unittests/SymbolFile/CMakeLists.txt

Modified: lldb/trunk/lit/SymbolFile/PDB/Inputs/VariablesLocationsTest.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/lit/SymbolFile/PDB/Inputs/VariablesLocationsTest.cpp?rev=352845&r1=352844&r2=352845&view=diff
==============================================================================
--- lldb/trunk/lit/SymbolFile/PDB/Inputs/VariablesLocationsTest.cpp (original)
+++ lldb/trunk/lit/SymbolFile/PDB/Inputs/VariablesLocationsTest.cpp Fri Feb  1 02:01:18 2019
@@ -5,11 +5,22 @@ void __fastcall foo(short arg_0, float a
   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;
 }

Modified: lldb/trunk/lit/SymbolFile/PDB/Inputs/VariablesLocationsTest.script
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/lit/SymbolFile/PDB/Inputs/VariablesLocationsTest.script?rev=352845&r1=352844&r2=352845&view=diff
==============================================================================
--- lldb/trunk/lit/SymbolFile/PDB/Inputs/VariablesLocationsTest.script (original)
+++ lldb/trunk/lit/SymbolFile/PDB/Inputs/VariablesLocationsTest.script Fri Feb  1 02:01:18 2019
@@ -1,4 +1,5 @@
 breakpoint set --file VariablesLocationsTest.cpp --line 6
+breakpoint set --file VariablesLocationsTest.cpp --line 15
 
 run
 
@@ -14,3 +15,11 @@ frame select 1
 
 frame variable loc_0
 frame variable loc_1
+
+continue
+
+frame variable arg_0
+
+frame variable loc_0
+frame variable loc_1
+

Modified: lldb/trunk/lit/SymbolFile/PDB/variables-locations.test
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/lit/SymbolFile/PDB/variables-locations.test?rev=352845&r1=352844&r2=352845&view=diff
==============================================================================
--- lldb/trunk/lit/SymbolFile/PDB/variables-locations.test (original)
+++ lldb/trunk/lit/SymbolFile/PDB/variables-locations.test Fri Feb  1 02:01:18 2019
@@ -1,5 +1,6 @@
 REQUIRES: system-windows, lld
 RUN: %build --compiler=clang-cl --output=%t.exe %S/Inputs/VariablesLocationsTest.cpp
+RUN: env LLDB_USE_NATIVE_PDB_READER=0 %lldb -b -s %S/Inputs/VariablesLocationsTest.script -- %t.exe | FileCheck %s
 RUN: env LLDB_USE_NATIVE_PDB_READER=1 %lldb -b -s %S/Inputs/VariablesLocationsTest.script -- %t.exe | FileCheck %s
 
 CHECK: g_var = 2222
@@ -12,3 +13,8 @@ CHECK: loc_1 = 0.567
 
 CHECK: loc_0 = true
 CHECK: loc_1 = 3333
+
+CHECK: arg_0 = 22
+
+CHECK: loc_0 = (a = 1234)
+CHECK: loc_1 = 5678

Modified: lldb/trunk/source/Expression/DWARFExpression.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Expression/DWARFExpression.cpp?rev=352845&r1=352844&r2=352845&view=diff
==============================================================================
--- lldb/trunk/source/Expression/DWARFExpression.cpp (original)
+++ lldb/trunk/source/Expression/DWARFExpression.cpp Fri Feb  1 02:01:18 2019
@@ -3203,7 +3203,7 @@ static bool print_dwarf_exp_op(Stream &s
     break;
   default:
     s.Printf("UNKNOWN ONE-OPERAND OPCODE, #%u", opcode);
-    return true;
+    return false;
   }
 
   switch (size) {
@@ -3249,7 +3249,7 @@ static bool print_dwarf_exp_op(Stream &s
     break;
   }
 
-  return false;
+  return true;
 }
 
 bool DWARFExpression::PrintDWARFExpression(Stream &s, const DataExtractor &data,

Modified: lldb/trunk/source/Plugins/SymbolFile/NativePDB/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/NativePDB/CMakeLists.txt?rev=352845&r1=352844&r2=352845&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/SymbolFile/NativePDB/CMakeLists.txt (original)
+++ lldb/trunk/source/Plugins/SymbolFile/NativePDB/CMakeLists.txt Fri Feb  1 02:01:18 2019
@@ -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 @@ add_lldb_library(lldbPluginSymbolFileNat
     clangLex
     lldbCore
     lldbSymbol
-	  lldbUtility
+    lldbUtility
   LINK_COMPONENTS
     DebugInfoCodeView
     DebugInfoPDB

Copied: lldb/trunk/source/Plugins/SymbolFile/NativePDB/CodeViewRegisterMapping.cpp (from r352780, lldb/trunk/source/Plugins/SymbolFile/PDB/PDBLocationToDWARFExpression.cpp)
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/NativePDB/CodeViewRegisterMapping.cpp?p2=lldb/trunk/source/Plugins/SymbolFile/NativePDB/CodeViewRegisterMapping.cpp&p1=lldb/trunk/source/Plugins/SymbolFile/PDB/PDBLocationToDWARFExpression.cpp&r1=352780&r2=352845&rev=352845&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/SymbolFile/PDB/PDBLocationToDWARFExpression.cpp (original)
+++ lldb/trunk/source/Plugins/SymbolFile/NativePDB/CodeViewRegisterMapping.cpp Fri Feb  1 02:01:18 2019
@@ -1,30 +1,21 @@
-//===-- PDBLocationToDWARFExpression.cpp ------------------------*- C++ -*-===//
+//===-- CodeViewRegisterMapping.cpp -----------------------------*- C++ -*-===//
 //
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
 //
 //===----------------------------------------------------------------------===//
 
-#include "PDBLocationToDWARFExpression.h"
-
-#include "lldb/Core/Section.h"
-#include "lldb/Core/StreamBuffer.h"
-#include "lldb/Core/dwarf.h"
-#include "lldb/Expression/DWARFExpression.h"
-#include "lldb/Utility/DataBufferHeap.h"
+#include "CodeViewRegisterMapping.h"
 
-#include "llvm/DebugInfo/CodeView/CodeView.h"
-#include "llvm/DebugInfo/PDB/PDBSymbolData.h"
+#include "lldb/lldb-defines.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[] = {
+static const uint32_t g_code_view_to_lldb_registers_x86[] = {
     LLDB_INVALID_REGNUM, // NONE
     lldb_al_i386,        // AL
     lldb_cl_i386,        // CL
@@ -152,7 +143,7 @@ const uint32_t g_code_view_to_lldb_regis
     lldb_xmm7_i386       // XMM7
 };
 
-const uint32_t g_code_view_to_lldb_registers_x86_64[] = {
+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
@@ -431,8 +422,8 @@ const uint32_t g_code_view_to_lldb_regis
     lldb_bnd2_x86_64  // BND2
 };
 
-uint32_t GetLLDBRegisterNumber(llvm::Triple::ArchType arch_type,
-                               llvm::codeview::RegisterId register_id) {
+uint32_t lldb_private::npdb::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) <
@@ -465,120 +456,3 @@ uint32_t GetLLDBRegisterNumber(llvm::Tri
     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;
-}
-
-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);
-}
-} // namespace
-
-DWARFExpression ConvertPDBLocationToDWARFExpression(ModuleSP module,
-                                                    const PDBSymbolData &symbol,
-                                                    bool &is_constant) {
-  is_constant = true;
-
-  if (!module)
-    return DWARFExpression(nullptr);
-
-  const ArchSpec &architecture = module->GetArchitecture();
-  llvm::Triple::ArchType arch_type = architecture.GetMachine();
-  ByteOrder byte_order = architecture.GetByteOrder();
-  uint32_t address_size = architecture.GetAddressByteSize();
-  uint32_t byte_size = architecture.GetDataByteSize();
-  if (byte_order == eByteOrderInvalid || address_size == 0)
-    return DWARFExpression(nullptr);
-
-  RegisterKind register_kind = eRegisterKindDWARF;
-  StreamBuffer<32> stream(Stream::eBinary, address_size, byte_order);
-  switch (symbol.getLocationType()) {
-  case PDB_LocType::Static:
-  case PDB_LocType::TLS: {
-    stream.PutHex8(DW_OP_addr);
-
-    SectionList *section_list = module->GetSectionList();
-    if (!section_list)
-      return DWARFExpression(nullptr);
-
-    uint32_t section_idx = symbol.getAddressSection() - 1;
-    if (section_idx >= section_list->GetSize())
-      return DWARFExpression(nullptr);
-
-    auto section = section_list->GetSectionAtIndex(section_idx);
-    if (!section)
-      return DWARFExpression(nullptr);
-
-    uint32_t offset = symbol.getAddressOffset();
-    stream.PutMaxHex64(section->GetFileAddress() + offset, address_size,
-                       byte_order);
-
-    is_constant = false;
-
-    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);
-
-    if (reg_num > 31) {
-      stream.PutHex8(DW_OP_bregx);
-      stream.PutULEB128(reg_num);
-    } else
-      stream.PutHex8(DW_OP_breg0 + reg_num);
-
-    int32_t offset = symbol.getOffset();
-    stream.PutSLEB128(offset);
-
-    is_constant = false;
-
-    break;
-  }
-  case PDB_LocType::Enregistered: {
-    uint32_t reg_num =
-        GetRegisterNumber(arch_type, symbol.getRegisterId(), register_kind);
-    if (reg_num == LLDB_INVALID_REGNUM)
-      return DWARFExpression(nullptr);
-
-    if (reg_num > 31) {
-      stream.PutHex8(DW_OP_regx);
-      stream.PutULEB128(reg_num);
-    } else
-      stream.PutHex8(DW_OP_reg0 + reg_num);
-
-    is_constant = false;
-
-    break;
-  }
-  case PDB_LocType::Constant: {
-    Variant value = symbol.getValue();
-    stream.PutRawBytes(&value.Value, sizeof(value.Value),
-                       endian::InlHostByteOrder());
-    break;
-  }
-  default:
-    return DWARFExpression(nullptr);
-  }
-
-  DataBufferSP buffer =
-      std::make_shared<DataBufferHeap>(stream.GetData(), stream.GetSize());
-  DataExtractor extractor(buffer, byte_order, address_size, byte_size);
-  DWARFExpression result(module, extractor, nullptr, 0, buffer->GetByteSize());
-  result.SetRegisterKind(register_kind);
-
-  return result;
-}

Added: lldb/trunk/source/Plugins/SymbolFile/NativePDB/CodeViewRegisterMapping.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/NativePDB/CodeViewRegisterMapping.h?rev=352845&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/SymbolFile/NativePDB/CodeViewRegisterMapping.h (added)
+++ lldb/trunk/source/Plugins/SymbolFile/NativePDB/CodeViewRegisterMapping.h Fri Feb  1 02:01:18 2019
@@ -0,0 +1,25 @@
+//===-- 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"
+
+namespace lldb_private {
+namespace npdb {
+
+uint32_t GetLLDBRegisterNumber(llvm::Triple::ArchType arch_type,
+                               llvm::codeview::RegisterId register_id);
+
+} // namespace npdb
+} // namespace lldb_private
+
+#endif

Modified: lldb/trunk/source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.cpp?rev=352845&r1=352844&r2=352845&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.cpp (original)
+++ lldb/trunk/source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.cpp Fri Feb  1 02:01:18 2019
@@ -8,7 +8,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"
@@ -23,6 +22,8 @@
 #include "llvm/Support/Endian.h"
 
 #include "PdbUtil.h"
+#include "CodeViewRegisterMapping.h"
+#include "PdbFPOProgramToDWARFExpression.h"
 
 using namespace lldb;
 using namespace lldb_private;
@@ -30,448 +31,6 @@ using namespace lldb_private::npdb;
 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;
@@ -609,6 +168,33 @@ DWARFExpression lldb_private::npdb::Make
   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);

Modified: lldb/trunk/source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.h?rev=352845&r1=352844&r2=352845&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.h (original)
+++ lldb/trunk/source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.h Fri Feb  1 02:01:18 2019
@@ -30,6 +30,9 @@ MakeEnregisteredLocationExpression(llvm:
 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(

Added: lldb/trunk/source/Plugins/SymbolFile/NativePDB/PdbFPOProgramToDWARFExpression.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/NativePDB/PdbFPOProgramToDWARFExpression.cpp?rev=352845&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/SymbolFile/NativePDB/PdbFPOProgramToDWARFExpression.cpp (added)
+++ lldb/trunk/source/Plugins/SymbolFile/NativePDB/PdbFPOProgramToDWARFExpression.cpp Fri Feb  1 02:01:18 2019
@@ -0,0 +1,528 @@
+//===-- 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 = npdb::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 lldb_private::npdb::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;
+}

Added: lldb/trunk/source/Plugins/SymbolFile/NativePDB/PdbFPOProgramToDWARFExpression.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/NativePDB/PdbFPOProgramToDWARFExpression.h?rev=352845&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/SymbolFile/NativePDB/PdbFPOProgramToDWARFExpression.h (added)
+++ lldb/trunk/source/Plugins/SymbolFile/NativePDB/PdbFPOProgramToDWARFExpression.h Fri Feb  1 02:01:18 2019
@@ -0,0 +1,29 @@
+//===-- 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;
+
+namespace npdb {
+  
+bool TranslateFPOProgramToDWARFExpression(llvm::StringRef program,
+                                          llvm::StringRef register_name,
+                                          llvm::Triple::ArchType arch_type,
+                                          lldb_private::Stream &stream);
+
+} // namespace npdb
+} // namespace lldb_private
+
+#endif

Modified: lldb/trunk/source/Plugins/SymbolFile/NativePDB/PdbIndex.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/NativePDB/PdbIndex.h?rev=352845&r1=352844&r2=352845&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/SymbolFile/NativePDB/PdbIndex.h (original)
+++ lldb/trunk/source/Plugins/SymbolFile/NativePDB/PdbIndex.h Fri Feb  1 02:01:18 2019
@@ -114,6 +114,7 @@ public:
       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; }

Modified: lldb/trunk/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp?rev=352845&r1=352844&r2=352845&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp (original)
+++ lldb/trunk/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp Fri Feb  1 02:01:18 2019
@@ -14,9 +14,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"
 
@@ -42,7 +44,7 @@ MakeRangeList(const PdbIndex &index, con
     gaps = gaps.drop_front();
   }
 
-  result.Append(start, end);
+  result.Append(start, end - start);
   return result;
 }
 
@@ -506,8 +508,78 @@ VariableInfo lldb_private::npdb::GetVari
   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);
 
@@ -542,13 +614,69 @@ VariableInfo lldb_private::npdb::GetVari
           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 = █
+      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!");

Modified: lldb/trunk/source/Plugins/SymbolFile/NativePDB/PdbUtil.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/NativePDB/PdbUtil.h?rev=352845&r1=352844&r2=352845&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/SymbolFile/NativePDB/PdbUtil.h (original)
+++ lldb/trunk/source/Plugins/SymbolFile/NativePDB/PdbUtil.h Fri Feb  1 02:01:18 2019
@@ -141,7 +141,7 @@ LookThroughModifierRecord(llvm::codeview
 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);

Modified: lldb/trunk/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp?rev=352845&r1=352844&r2=352845&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp (original)
+++ lldb/trunk/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp Fri Feb  1 02:01:18 2019
@@ -1315,7 +1315,9 @@ VariableSP SymbolFileNativePDB::CreateLo
                                                     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;
 

Modified: lldb/trunk/source/Plugins/SymbolFile/PDB/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/PDB/CMakeLists.txt?rev=352845&r1=352844&r2=352845&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/SymbolFile/PDB/CMakeLists.txt (original)
+++ lldb/trunk/source/Plugins/SymbolFile/PDB/CMakeLists.txt Fri Feb  1 02:01:18 2019
@@ -8,7 +8,7 @@ add_lldb_library(lldbPluginSymbolFilePDB
     clangLex
     lldbCore
     lldbSymbol
-	lldbUtility
+    lldbUtility
   lldbPluginSymbolFileNativePDB
   LINK_COMPONENTS
     DebugInfoPDB

Modified: lldb/trunk/source/Plugins/SymbolFile/PDB/PDBLocationToDWARFExpression.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/PDB/PDBLocationToDWARFExpression.cpp?rev=352845&r1=352844&r2=352845&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/SymbolFile/PDB/PDBLocationToDWARFExpression.cpp (original)
+++ lldb/trunk/source/Plugins/SymbolFile/PDB/PDBLocationToDWARFExpression.cpp Fri Feb  1 02:01:18 2019
@@ -12,483 +12,60 @@
 #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 lldb_private::npdb;
 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)
@@ -530,10 +107,32 @@ DWARFExpression ConvertPDBLocationToDWAR
     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);
@@ -549,8 +148,8 @@ DWARFExpression ConvertPDBLocationToDWAR
     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);
 

Modified: lldb/trunk/source/Plugins/SymbolFile/PDB/PDBLocationToDWARFExpression.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/PDB/PDBLocationToDWARFExpression.h?rev=352845&r1=352844&r2=352845&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/SymbolFile/PDB/PDBLocationToDWARFExpression.h (original)
+++ lldb/trunk/source/Plugins/SymbolFile/PDB/PDBLocationToDWARFExpression.h Fri Feb  1 02:01:18 2019
@@ -10,6 +10,7 @@
 #define lldb_Plugins_SymbolFile_PDB_PDBLocationToDWARFExpression_h_
 
 #include "lldb/Core/Module.h"
+#include "lldb/Symbol/Variable.h"
 
 namespace lldb_private {
 class DWARFExpression;
@@ -30,6 +31,9 @@ class PDBSymbolData;
 /// @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.
@@ -40,5 +44,6 @@ class PDBSymbolData;
 lldb_private::DWARFExpression
 ConvertPDBLocationToDWARFExpression(lldb::ModuleSP module,
                                     const llvm::pdb::PDBSymbolData &symbol,
+                                    const lldb_private::Variable::RangeList &ranges,
                                     bool &is_constant);
 #endif

Modified: lldb/trunk/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp?rev=352845&r1=352844&r2=352845&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp (original)
+++ lldb/trunk/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp Fri Feb  1 02:01:18 2019
@@ -933,12 +933,25 @@ VariableSP SymbolFilePDB::ParseVariableF
 
   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());
+      }
     }
   }
 
@@ -951,7 +964,7 @@ VariableSP SymbolFilePDB::ParseVariableF
 
   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,

Modified: lldb/trunk/unittests/SymbolFile/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/unittests/SymbolFile/CMakeLists.txt?rev=352845&r1=352844&r2=352845&view=diff
==============================================================================
--- lldb/trunk/unittests/SymbolFile/CMakeLists.txt (original)
+++ lldb/trunk/unittests/SymbolFile/CMakeLists.txt Fri Feb  1 02:01:18 2019
@@ -1,4 +1,5 @@
 add_subdirectory(DWARF)
+add_subdirectory(NativePDB)
 if (LLVM_ENABLE_DIA_SDK)
   add_subdirectory(PDB)
 endif()

Added: lldb/trunk/unittests/SymbolFile/NativePDB/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/unittests/SymbolFile/NativePDB/CMakeLists.txt?rev=352845&view=auto
==============================================================================
--- lldb/trunk/unittests/SymbolFile/NativePDB/CMakeLists.txt (added)
+++ lldb/trunk/unittests/SymbolFile/NativePDB/CMakeLists.txt Fri Feb  1 02:01:18 2019
@@ -0,0 +1,13 @@
+add_lldb_unittest(SymbolFileNativePDBTests
+  PdbFPOProgramToDWARFExpressionTests.cpp
+
+  LINK_LIBS
+    lldbCore
+    lldbHost
+    lldbSymbol
+    lldbPluginSymbolFileNativePDB
+    lldbUtilityHelpers
+  LINK_COMPONENTS
+    Support
+    DebugInfoPDB
+  )

Added: lldb/trunk/unittests/SymbolFile/NativePDB/PdbFPOProgramToDWARFExpressionTests.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/unittests/SymbolFile/NativePDB/PdbFPOProgramToDWARFExpressionTests.cpp?rev=352845&view=auto
==============================================================================
--- lldb/trunk/unittests/SymbolFile/NativePDB/PdbFPOProgramToDWARFExpressionTests.cpp (added)
+++ lldb/trunk/unittests/SymbolFile/NativePDB/PdbFPOProgramToDWARFExpressionTests.cpp Fri Feb  1 02:01:18 2019
@@ -0,0 +1,166 @@
+//===-- 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;
+using namespace lldb_private::npdb;
+
+/// 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");
+}




More information about the lldb-commits mailing list