zequanwu updated this revision to Diff 450408.
zequanwu added a comment.

- Recurse into parent classes when filling the offset to size map.
- Previously the range parsed earlier is preferred, now it's the range parsed 
later is preferred, since it makes the code cleaner and it doesn't really 
matter as long as it's consistent. Although overlapping ranges are allowed in 
RangeDataVector, I'm still trying to keep the RangeMap contains non-overlapping 
ranges, since only whole value ranges are allowed to overlap with each other, 
and subfield ranges should not overlap with each other or whole value ranges. 
It's easier just to keep all ranges non-overlapping.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D130796

Files:
  lldb/include/lldb/Utility/RangeMap.h
  lldb/source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.cpp
  lldb/source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.h
  lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp
  lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.h
  lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
  lldb/test/Shell/SymbolFile/NativePDB/Inputs/local-variables-registers.lldbinit
  lldb/test/Shell/SymbolFile/NativePDB/inline_sites.test
  lldb/test/Shell/SymbolFile/NativePDB/local-variables-registers.s
  lldb/test/Shell/SymbolFile/NativePDB/subfield_register_simple_type.s

Index: lldb/test/Shell/SymbolFile/NativePDB/subfield_register_simple_type.s
===================================================================
--- lldb/test/Shell/SymbolFile/NativePDB/subfield_register_simple_type.s
+++ /dev/null
@@ -1,433 +0,0 @@
-# clang-format off
-# REQUIRES: lld, x86
-
-# RUN: %clang_cl --target=i386-windows-msvc -c /Fo%t.obj -- %s
-# RUN: lld-link /debug:full /nodefaultlib /entry:main %t.obj /out:%t.exe /base:0x400000
-# RUN: env LLDB_USE_NATIVE_PDB_READER=1 %lldb -f %t.exe -s \
-# RUN:     %p/Inputs/subfield_register_simple_type.lldbinit 2>&1 | FileCheck %s
-
-# This file is compiled from following source file:
-# clang-cl --target=i386-windows-msvc /Z7 /O1 -c /Fa a.cpp
-# __int64 __attribute__((optnone)) bar(__int64 x) { return x; };
-# __int64 foo(__int64 x) {
-#   return bar(x);
-# }
-#
-# int main(int argc, char** argv) {
-#   foo(argc);
-#   return 0;
-# }
-
-# FIXME: The following variable location have wrong register numbers due to
-# https://github.com/llvm/llvm-project/issues/53575. Fix them after resolving
-# the issue.
-
-# CHECK:      (lldb) image lookup -a 0x40102f -v
-# CHECK:      LineEntry: [0x00401026-0x00401039): C:\src\a.cpp:3
-# CHECK-NEXT: Variable: id = {{.*}}, name = "x", type = "int64_t", valid ranges = [0x0040102f-0x00401036), location = DW_OP_reg0 EAX, DW_OP_piece 0x4, DW_OP_reg2 EDX, DW_OP_piece 0x4, decl =
-
-	.text
-	.def	@feat.00;
-	.scl	3;
-	.type	0;
-	.endef
-	.globl	@feat.00
-.set @feat.00, 1
-	.intel_syntax noprefix
-	.file	"a.cpp"
-	.def	"?bar@@YA_J_J@Z";
-	.scl	2;
-	.type	32;
-	.endef
-	.section	.text,"xr",one_only,"?bar@@YA_J_J@Z"
-	.globl	"?bar@@YA_J_J@Z"                # -- Begin function ?bar@@YA_J_J@Z
-	.p2align	4, 0x90
-"?bar@@YA_J_J@Z":                       # @"?bar@@YA_J_J@Z"
-Lfunc_begin0:
-	.cv_func_id 0
-	.cv_file	1 "C:\\src\\a.cpp" "CB99424BC3DD1AB059A2DBC6841147F2" 1
-	.cv_loc	0 1 1 0                         # a.cpp:1:0
-	.cv_fpo_proc	"?bar@@YA_J_J@Z" 8
-# %bb.0:                                # %entry
-	push	ebp
-	.cv_fpo_pushreg	ebp
-	mov	ebp, esp
-	.cv_fpo_setframe	ebp
-	and	esp, -8
-	.cv_fpo_stackalign	8
-	sub	esp, 8
-	.cv_fpo_stackalloc	8
-	.cv_fpo_endprologue
-	mov	eax, dword ptr [ebp + 8]
-	mov	ecx, dword ptr [ebp + 12]
-	mov	dword ptr [esp], eax
-	mov	dword ptr [esp + 4], ecx
-Ltmp0:
-	mov	eax, dword ptr [esp]
-	mov	edx, dword ptr [esp + 4]
-	mov	esp, ebp
-	pop	ebp
-	ret
-Ltmp1:
-	.cv_fpo_endproc
-Lfunc_end0:
-                                        # -- End function
-	.def	"?foo@@YA_J_J@Z";
-	.scl	2;
-	.type	32;
-	.endef
-	.section	.text,"xr",one_only,"?foo@@YA_J_J@Z"
-	.globl	"?foo@@YA_J_J@Z"                # -- Begin function ?foo@@YA_J_J@Z
-"?foo@@YA_J_J@Z":                       # @"?foo@@YA_J_J@Z"
-Lfunc_begin1:
-	.cv_func_id 1
-	.cv_fpo_proc	"?foo@@YA_J_J@Z" 8
-# %bb.0:                                # %entry
-	#DEBUG_VALUE: foo:x <- [DW_OP_plus_uconst 4] [$esp+0]
-	.cv_loc	1 1 3 0                         # a.cpp:3:0
-	jmp	"?bar@@YA_J_J@Z"                # TAILCALL
-Ltmp2:
-	.cv_fpo_endproc
-Lfunc_end1:
-                                        # -- End function
-	.def	_main;
-	.scl	2;
-	.type	32;
-	.endef
-	.section	.text,"xr",one_only,_main
-	.globl	_main                           # -- Begin function main
-_main:                                  # @main
-Lfunc_begin2:
-	.cv_func_id 2
-	.cv_loc	2 1 6 0                         # a.cpp:6:0
-	.cv_fpo_proc	_main 8
-# %bb.0:                                # %entry
-	#DEBUG_VALUE: main:argv <- [DW_OP_plus_uconst 8] [$esp+0]
-	#DEBUG_VALUE: main:argc <- [DW_OP_plus_uconst 4] [$esp+0]
-	.cv_inline_site_id 3 within 2 inlined_at 1 7 0
-	.cv_loc	3 1 3 0                         # a.cpp:3:0
-	mov	eax, dword ptr [esp + 4]
-	mov	ecx, eax
-	sar	ecx, 31
-Ltmp3:
-	#DEBUG_VALUE: foo:x <- [DW_OP_LLVM_fragment 0 32] $eax
-	#DEBUG_VALUE: foo:x <- [DW_OP_LLVM_fragment 32 32] $ecx
-	push	ecx
-Ltmp4:
-	push	eax
-	call	"?bar@@YA_J_J@Z"
-Ltmp5:
-	add	esp, 8
-Ltmp6:
-	.cv_loc	2 1 8 0                         # a.cpp:8:0
-	xor	eax, eax
-	ret
-Ltmp7:
-	.cv_fpo_endproc
-Lfunc_end2:
-                                        # -- End function
-	.section	.drectve,"yn"
-	.ascii	" /DEFAULTLIB:libcmt.lib"
-	.ascii	" /DEFAULTLIB:oldnames.lib"
-	.section	.debug$S,"dr"
-	.p2align	2
-	.long	4                               # Debug section magic
-	.long	241
-	.long	Ltmp9-Ltmp8                     # Subsection size
-Ltmp8:
-	.short	Ltmp11-Ltmp10                   # Record length
-Ltmp10:
-	.short	4353                            # Record kind: S_OBJNAME
-	.long	0                               # Signature
-	.asciz	"C:\\src\\a.obj"                # Object name
-	.p2align	2
-Ltmp11:
-	.short	Ltmp13-Ltmp12                   # Record length
-Ltmp12:
-	.short	4412                            # Record kind: S_COMPILE3
-	.long	1                               # Flags and language
-	.short	7                               # CPUType
-	.short	15                              # Frontend version
-	.short	0
-	.short	0
-	.short	0
-	.short	15000                           # Backend version
-	.short	0
-	.short	0
-	.short	0
-	.asciz	"clang version 15.0.0"          # Null-terminated compiler version string
-	.p2align	2
-Ltmp13:
-Ltmp9:
-	.p2align	2
-	.long	246                             # Inlinee lines subsection
-	.long	Ltmp15-Ltmp14                   # Subsection size
-Ltmp14:
-	.long	0                               # Inlinee lines signature
-
-                                        # Inlined function foo starts at a.cpp:2
-	.long	4098                            # Type index of inlined function
-	.cv_filechecksumoffset	1               # Offset into filechecksum table
-	.long	2                               # Starting line number
-Ltmp15:
-	.p2align	2
-	.section	.debug$S,"dr",associative,"?bar@@YA_J_J@Z"
-	.p2align	2
-	.long	4                               # Debug section magic
-	.cv_fpo_data	"?bar@@YA_J_J@Z"
-	.long	241                             # Symbol subsection for bar
-	.long	Ltmp17-Ltmp16                   # Subsection size
-Ltmp16:
-	.short	Ltmp19-Ltmp18                   # Record length
-Ltmp18:
-	.short	4423                            # Record kind: S_GPROC32_ID
-	.long	0                               # PtrParent
-	.long	0                               # PtrEnd
-	.long	0                               # PtrNext
-	.long	Lfunc_end0-"?bar@@YA_J_J@Z"     # Code size
-	.long	0                               # Offset after prologue
-	.long	0                               # Offset before epilogue
-	.long	4099                            # Function type index
-	.secrel32	"?bar@@YA_J_J@Z"        # Function section relative address
-	.secidx	"?bar@@YA_J_J@Z"                # Function section index
-	.byte	0                               # Flags
-	.asciz	"bar"                           # Function name
-	.p2align	2
-Ltmp19:
-	.short	Ltmp21-Ltmp20                   # Record length
-Ltmp20:
-	.short	4114                            # Record kind: S_FRAMEPROC
-	.long	12                              # FrameSize
-	.long	0                               # Padding
-	.long	0                               # Offset of padding
-	.long	0                               # Bytes of callee saved registers
-	.long	0                               # Exception handler offset
-	.short	0                               # Exception handler section
-	.long	147456                          # Flags (defines frame register)
-	.p2align	2
-Ltmp21:
-	.short	Ltmp23-Ltmp22                   # Record length
-Ltmp22:
-	.short	4414                            # Record kind: S_LOCAL
-	.long	19                              # TypeIndex
-	.short	1                               # Flags
-	.asciz	"x"
-	.p2align	2
-Ltmp23:
-	.cv_def_range	 Ltmp0 Ltmp1, reg_rel, 30006, 0, -8
-	.short	2                               # Record length
-	.short	4431                            # Record kind: S_PROC_ID_END
-Ltmp17:
-	.p2align	2
-	.cv_linetable	0, "?bar@@YA_J_J@Z", Lfunc_end0
-	.section	.debug$S,"dr",associative,"?foo@@YA_J_J@Z"
-	.p2align	2
-	.long	4                               # Debug section magic
-	.cv_fpo_data	"?foo@@YA_J_J@Z"
-	.long	241                             # Symbol subsection for foo
-	.long	Ltmp25-Ltmp24                   # Subsection size
-Ltmp24:
-	.short	Ltmp27-Ltmp26                   # Record length
-Ltmp26:
-	.short	4423                            # Record kind: S_GPROC32_ID
-	.long	0                               # PtrParent
-	.long	0                               # PtrEnd
-	.long	0                               # PtrNext
-	.long	Lfunc_end1-"?foo@@YA_J_J@Z"     # Code size
-	.long	0                               # Offset after prologue
-	.long	0                               # Offset before epilogue
-	.long	4098                            # Function type index
-	.secrel32	"?foo@@YA_J_J@Z"        # Function section relative address
-	.secidx	"?foo@@YA_J_J@Z"                # Function section index
-	.byte	0                               # Flags
-	.asciz	"foo"                           # Function name
-	.p2align	2
-Ltmp27:
-	.short	Ltmp29-Ltmp28                   # Record length
-Ltmp28:
-	.short	4114                            # Record kind: S_FRAMEPROC
-	.long	0                               # FrameSize
-	.long	0                               # Padding
-	.long	0                               # Offset of padding
-	.long	0                               # Bytes of callee saved registers
-	.long	0                               # Exception handler offset
-	.short	0                               # Exception handler section
-	.long	0                               # Flags (defines frame register)
-	.p2align	2
-Ltmp29:
-	.short	Ltmp31-Ltmp30                   # Record length
-Ltmp30:
-	.short	4414                            # Record kind: S_LOCAL
-	.long	19                              # TypeIndex
-	.short	1                               # Flags
-	.asciz	"x"
-	.p2align	2
-Ltmp31:
-	.cv_def_range	 Lfunc_begin1 Lfunc_end1, reg_rel, 30006, 0, 4
-	.short	2                               # Record length
-	.short	4431                            # Record kind: S_PROC_ID_END
-Ltmp25:
-	.p2align	2
-	.cv_linetable	1, "?foo@@YA_J_J@Z", Lfunc_end1
-	.section	.debug$S,"dr",associative,_main
-	.p2align	2
-	.long	4                               # Debug section magic
-	.cv_fpo_data	_main
-	.long	241                             # Symbol subsection for main
-	.long	Ltmp33-Ltmp32                   # Subsection size
-Ltmp32:
-	.short	Ltmp35-Ltmp34                   # Record length
-Ltmp34:
-	.short	4423                            # Record kind: S_GPROC32_ID
-	.long	0                               # PtrParent
-	.long	0                               # PtrEnd
-	.long	0                               # PtrNext
-	.long	Lfunc_end2-_main                # Code size
-	.long	0                               # Offset after prologue
-	.long	0                               # Offset before epilogue
-	.long	4103                            # Function type index
-	.secrel32	_main                   # Function section relative address
-	.secidx	_main                           # Function section index
-	.byte	0                               # Flags
-	.asciz	"main"                          # Function name
-	.p2align	2
-Ltmp35:
-	.short	Ltmp37-Ltmp36                   # Record length
-Ltmp36:
-	.short	4114                            # Record kind: S_FRAMEPROC
-	.long	0                               # FrameSize
-	.long	0                               # Padding
-	.long	0                               # Offset of padding
-	.long	0                               # Bytes of callee saved registers
-	.long	0                               # Exception handler offset
-	.short	0                               # Exception handler section
-	.long	0                               # Flags (defines frame register)
-	.p2align	2
-Ltmp37:
-	.short	Ltmp39-Ltmp38                   # Record length
-Ltmp38:
-	.short	4414                            # Record kind: S_LOCAL
-	.long	116                             # TypeIndex
-	.short	1                               # Flags
-	.asciz	"argc"
-	.p2align	2
-Ltmp39:
-	.cv_def_range	 Lfunc_begin2 Ltmp4, reg_rel, 30006, 0, 4
-	.short	Ltmp41-Ltmp40                   # Record length
-Ltmp40:
-	.short	4414                            # Record kind: S_LOCAL
-	.long	4100                            # TypeIndex
-	.short	1                               # Flags
-	.asciz	"argv"
-	.p2align	2
-Ltmp41:
-	.cv_def_range	 Lfunc_begin2 Ltmp4, reg_rel, 30006, 0, 8
-	.short	Ltmp43-Ltmp42                   # Record length
-Ltmp42:
-	.short	4429                            # Record kind: S_INLINESITE
-	.long	0                               # PtrParent
-	.long	0                               # PtrEnd
-	.long	4098                            # Inlinee type index
-	.cv_inline_linetable	3 1 2 Lfunc_begin2 Lfunc_end2
-	.p2align	2
-Ltmp43:
-	.short	Ltmp45-Ltmp44                   # Record length
-Ltmp44:
-	.short	4414                            # Record kind: S_LOCAL
-	.long	19                              # TypeIndex
-	.short	1                               # Flags
-	.asciz	"x"
-	.p2align	2
-Ltmp45:
-	.cv_def_range	 Ltmp3 Ltmp5, subfield_reg, 17, 0
-	.cv_def_range	 Ltmp3 Ltmp5, subfield_reg, 18, 4
-	.short	2                               # Record length
-	.short	4430                            # Record kind: S_INLINESITE_END
-	.short	2                               # Record length
-	.short	4431                            # Record kind: S_PROC_ID_END
-Ltmp33:
-	.p2align	2
-	.cv_linetable	2, _main, Lfunc_end2
-	.section	.debug$S,"dr"
-	.cv_filechecksums                       # File index to string table offset subsection
-	.cv_stringtable                         # String table
-	.long	241
-	.long	Ltmp47-Ltmp46                   # Subsection size
-Ltmp46:
-	.short	Ltmp49-Ltmp48                   # Record length
-Ltmp48:
-	.short	4428                            # Record kind: S_BUILDINFO
-	.long	4109                            # LF_BUILDINFO index
-	.p2align	2
-Ltmp49:
-Ltmp47:
-	.p2align	2
-	.section	.debug$T,"dr"
-	.p2align	2
-	.long	4                               # Debug section magic
-	# ArgList (0x1000)
-	.short	0xa                             # Record length
-	.short	0x1201                          # Record kind: LF_ARGLIST
-	.long	0x1                             # NumArgs
-	.long	0x13                            # Argument: __int64
-	# Procedure (0x1001)
-	.short	0xe                             # Record length
-	.short	0x1008                          # Record kind: LF_PROCEDURE
-	.long	0x13                            # ReturnType: __int64
-	.byte	0x0                             # CallingConvention: NearC
-	.byte	0x0                             # FunctionOptions
-	.short	0x1                             # NumParameters
-	.long	0x1000                          # ArgListType: (__int64)
-	# FuncId (0x1002)
-	.short	0xe                             # Record length
-	.short	0x1601                          # Record kind: LF_FUNC_ID
-	.long	0x0                             # ParentScope
-	.long	0x1001                          # FunctionType: __int64 (__int64)
-	.asciz	"foo"                           # Name
-	# FuncId (0x1003)
-	.short	0xe                             # Record length
-	.short	0x1601                          # Record kind: LF_FUNC_ID
-	.long	0x0                             # ParentScope
-	.long	0x1001                          # FunctionType: __int64 (__int64)
-	.asciz	"bar"                           # Name
-	# Pointer (0x1004)
-	.short	0xa                             # Record length
-	.short	0x1002                          # Record kind: LF_POINTER
-	.long	0x470                           # PointeeType: char*
-	.long	0x800a                          # Attrs: [ Type: Near32, Mode: Pointer, SizeOf: 4 ]
-	# ArgList (0x1005)
-	.short	0xe                             # Record length
-	.short	0x1201                          # Record kind: LF_ARGLIST
-	.long	0x2                             # NumArgs
-	.long	0x74                            # Argument: int
-	.long	0x1004                          # Argument: char**
-	# Procedure (0x1006)
-	.short	0xe                             # Record length
-	.short	0x1008                          # Record kind: LF_PROCEDURE
-	.long	0x74                            # ReturnType: int
-	.byte	0x0                             # CallingConvention: NearC
-	.byte	0x0                             # FunctionOptions
-	.short	0x2                             # NumParameters
-	.long	0x1005                          # ArgListType: (int, char**)
-	# FuncId (0x1007)
-	.short	0x12                            # Record length
-	.short	0x1601                          # Record kind: LF_FUNC_ID
-	.long	0x0                             # ParentScope
-	.long	0x1006                          # FunctionType: int (int, char**)
-	.asciz	"main"                          # Name
-	.byte	243
-	.byte	242
-	.byte	241
-	# StringId (0x1008)
-	.short	0xe                             # Record length
-	.short	0x1605                          # Record kind: LF_STRING_ID
-	.long	0x0                             # Id
-	.asciz	"C:\\src"                       # StringData
-	.byte	241
-	# StringId (0x1009)
-	.short	0xe                             # Record length
-	.short	0x1605                          # Record kind: LF_STRING_ID
-	.long	0x0                             # Id
-	.asciz	"a.cpp"                         # StringData
-	.byte	242
-	.byte	241
Index: lldb/test/Shell/SymbolFile/NativePDB/local-variables-registers.s
===================================================================
--- lldb/test/Shell/SymbolFile/NativePDB/local-variables-registers.s
+++ lldb/test/Shell/SymbolFile/NativePDB/local-variables-registers.s
@@ -34,39 +34,38 @@
 
 # CHECK:      (lldb) image lookup -a 0x140001000 -v
 # CHECK:          LineEntry: [0x0000000140001000-0x0000000140001003): C:\src\test\a.cpp:10
-# CHECK-NEXT:      Variable: id = {{.*}}, name = "p1", type = "int", valid ranges = [0x0000000140001000-0x0000000140001003), location = DW_OP_reg26 XMM9
-# CHECK-NEXT:      Variable: id = {{.*}}, name = "p2", type = "char", valid ranges = [0x0000000140001000-0x0000000140001006), location = DW_OP_regx 0x3f
+# CHECK-NEXT:      Variable: id = {{.*}}, name = "p1", type = "int", valid ranges = <block>, location = [0x0000000140001000, 0x0000000140001003) -> DW_OP_reg26 XMM9
+# CHECK-NEXT:      Variable: id = {{.*}}, name = "p2", type = "char", valid ranges = <block>, location = [0x0000000140001000, 0x0000000140001006) -> DW_OP_regx 0x3f
 # CHECK-EMPTY:
 # CHECK:      (lldb) image lookup -a 0x140001003 -v
 # CHECK:          LineEntry: [0x0000000140001003-0x0000000140001006): C:\src\test\a.cpp:11
-# CHECK-NEXT:      Variable: id = {{.*}}, name = "p2", type = "char", valid ranges = [0x0000000140001000-0x0000000140001006), location = DW_OP_regx 0x3f
+# CHECK-NEXT:      Variable: id = {{.*}}, name = "p2", type = "char", valid ranges = <block>, location = [0x0000000140001000, 0x0000000140001006) -> DW_OP_regx 0x3f
+# CHECK-NEXT:      Variable: id = {{.*}}, name = "s", type = "S", valid ranges = <block>, location = [0x0000000140001003, 0x0000000140001006) -> DW_OP_piece 0x4, DW_OP_regx 0x3f, DW_OP_piece 0x1, DW_OP_piece 0x3
 # CHECK-EMPTY:
 # CHECK:      (lldb) image lookup -a 0x140001006 -v
 # CHECK:          LineEntry: [0x0000000140001006-0x0000000140001011): C:\src\test\a.cpp:12
-# CHECK-NEXT:      Variable: id = {{.*}}, name = "s", type = "S", valid ranges = [0x0000000140001006-0x0000000140001011), location = DW_OP_reg26 XMM9, DW_OP_piece 0x4, DW_OP_regx 0x3f, DW_OP_piece 0x1
+# CHECK-NEXT:      Variable: id = {{.*}}, name = "s", type = "S", valid ranges = <block>, location = [0x0000000140001006, 0x0000000140001011) -> DW_OP_reg26 XMM9, DW_OP_piece 0x4, DW_OP_regx 0x3f, DW_OP_piece 0x1, DW_OP_piece 0x3
 # CHECK-EMPTY:
 # CHECK:      (lldb) image lookup -a 0x140001011 -v
 # CHECK:          LineEntry: [0x0000000140001011-0x0000000140001015): C:\src\test\a.cpp:15
-# CHECK-NEXT:      Variable: id = {{.*}}, name = "argc", type = "int", valid ranges = [0x0000000140001011-0x0000000140001017), location = DW_OP_reg26 XMM9
-# CHECK-NEXT:      Variable: id = {{.*}}, name = "argv", type = "char **", valid ranges = [0x0000000140001011-0x0000000140001019), location = DW_OP_reg3 RBX
+# CHECK-NEXT:      Variable: id = {{.*}}, name = "argc", type = "int", valid ranges = <block>, location = [0x0000000140001011, 0x0000000140001017) -> DW_OP_reg26 XMM9
+# CHECK-NEXT:      Variable: id = {{.*}}, name = "argv", type = "char **", valid ranges = <block>, location = [0x0000000140001011, 0x0000000140001019) -> DW_OP_reg3 RBX
 # CHECK-EMPTY:
 # CHECK:      (lldb) image lookup -a 0x140001017 -v
 # CHECK:          LineEntry: [0x0000000140001017-0x000000014000101e): C:\src\test\a.cpp:17
-# CHECK-NEXT:      Variable: id = {{.*}}, name = "argv", type = "char **", valid ranges = [0x0000000140001011-0x0000000140001019), location = DW_OP_reg3 RBX
-# CHECK-NEXT:      Variable: id = {{.*}}, name = "local", type = "int", valid ranges = [0x0000000140001017-0x000000014000101e), location = DW_OP_reg26 XMM9
+# CHECK-NEXT:      Variable: id = {{.*}}, name = "argv", type = "char **", valid ranges = <block>, location = [0x0000000140001011, 0x0000000140001019) -> DW_OP_reg3 RBX
+# CHECK-NEXT:      Variable: id = {{.*}}, name = "local", type = "int", valid ranges = <block>, location = [0x0000000140001017, 0x000000014000101e) -> DW_OP_reg26 XMM9
 # CHECK-EMPTY:
 # CHECK:      (lldb) image lookup -a 0x140001019 -v
 # CHECK:          LineEntry: [0x0000000140001017-0x000000014000101e): C:\src\test\a.cpp:17
-# CHECK-NEXT:      Variable: id = {{.*}}, name = "local", type = "int", valid ranges = [0x0000000140001017-0x000000014000101e), location = DW_OP_reg26 XMM9
+# CHECK-NEXT:      Variable: id = {{.*}}, name = "local", type = "int", valid ranges = <block>, location = [0x0000000140001017, 0x000000014000101e) -> DW_OP_reg26 XMM9
 # CHECK-EMPTY:
 # CHECK:      (lldb) image lookup -a 0x14000101e -v
 # CHECK:          LineEntry: [0x000000014000101e-0x0000000140001031): C:\src\test\a.cpp:18
-# CHECK-NEXT:      Variable: id = {{.*}}, name = "s", type = "S", valid ranges = [0x000000014000101e-0x000000014000102c), location = DW_OP_reg24 XMM7, DW_OP_piece 0x4, DW_OP_piece 0x1
+# CHECK-NEXT:      Variable: id = {{.*}}, name = "s", type = "S", valid ranges = <block>, location = [0x000000014000101e, 0x000000014000102c) -> DW_OP_reg24 XMM7, DW_OP_piece 0x4, DW_OP_piece 0x4
 # CHECK-EMPTY:
 # CHECK:      (lldb) image lookup -a 0x14000102c -v
 # CHECK:          LineEntry: [0x000000014000101e-0x0000000140001031): C:\src\test\a.cpp:18
-# CHECK-EMPTY:
-
 
 	.text
 	.def	 @feat.00;
@@ -153,6 +152,72 @@
 .Ltmp7:
 	add	rsp, 40
 	ret
+# Manually created for testing purpose.
+.L31:
+	.cv_loc	1 1 1000 0                        # a.cpp:1000:0
+	ret
+.L32:
+	ret
+.L33:
+	ret
+.L34:
+	.cv_loc	1 1 1001 0                        # a.cpp:1001:0
+	ret
+.L35:
+	ret
+.L36:
+	ret
+.L37:
+	ret
+.L38:
+	ret
+.L39:
+	ret
+.L3a:
+	ret
+.L3b:
+	.cv_loc	1 1 1002 0                        # a.cpp:1002:0
+	ret
+.L3c:
+	ret
+.L3d:
+	ret
+.L3e:
+	ret
+.L3f:
+	ret
+.L40:
+	ret
+.L41:
+	ret
+.L42:
+	ret
+.L43:
+	ret
+.L44:
+	ret
+.L45:
+	.cv_loc	1 1 1003 0                        # a.cpp:1003:0
+	ret
+.L46:
+	ret
+.L47:
+	ret
+.L48:
+	ret
+.L49:
+	ret
+.L4a:
+	ret
+.L4b:
+	ret
+.L4c:
+	ret
+.L4d:
+	ret
+.L4e:
+	ret
+.Lend:
 .Ltmp8:
 .Lfunc_end1:
 	.seh_endproc
@@ -322,8 +387,152 @@
 	.p2align	2
 .Ltmp38:
 	.cv_def_range	 .Ltmp6 .Ltmp7, subfield_reg, 17, 0
-	.short	2                               # Record length
-	.short	4431                            # Record kind: S_PROC_ID_END
+ 	.short	.Ltmp101-.Ltmp100
+# Manually created debug info for testing purpose.
+# 1. Test non-overlapped ranges.
+.Ltmp100:
+	.short	4414                            # Record kind: S_LOCAL
+	.long	4109                            # TypeIndex
+	.short	0                               # Flags
+	.asciz	"non_overlapped_ranges"
+	.p2align	2
+.Ltmp101:
+	.cv_def_range	.L31 .L32, reg, 331
+	.cv_def_range	.L32 .L33, reg, 330
+	.cv_def_range	.L33 .L34, reg, 336
+	.short	.Ltmp103-.Ltmp102
+# CHECK:      (lldb) image lookup -a 0x140001031 -v
+# CHECK:          LineEntry: [0x0000000140001031-0x0000000140001034): C:\src\test\a.cpp:1000
+# CHECK-NEXT:      Variable: id = {{.*}}, name = "non_overlapped_ranges", type = "S1", valid ranges = <block>, location = [0x0000000140001031, 0x0000000140001032) -> DW_OP_reg3 RBX
+# CHECK-EMPTY:
+# CHECK:      (lldb) image lookup -a 0x140001032 -v
+# CHECK:          LineEntry: [0x0000000140001031-0x0000000140001034): C:\src\test\a.cpp:1000
+# CHECK-NEXT:      Variable: id = {{.*}}, name = "non_overlapped_ranges", type = "S1", valid ranges = <block>, location = [0x0000000140001032, 0x0000000140001033) -> DW_OP_reg2 RCX
+# CHECK-EMPTY:
+# CHECK:      (lldb) image lookup -a 0x140001033 -v
+# CHECK:          LineEntry: [0x0000000140001031-0x0000000140001034): C:\src\test\a.cpp:1000
+# CHECK-NEXT:      Variable: id = {{.*}}, name = "non_overlapped_ranges", type = "S1", valid ranges = <block>, location = [0x0000000140001033, 0x0000000140001034) -> DW_OP_reg8 R8
+# CHECK-EMPTY:
+
+# 2. Test overlapped subfield/reg_rel ranges at different offsets.
+.Ltmp102:
+ 	.short	4414                            # Record kind: S_LOCAL
+ 	.long	4109                            # TypeIndex
+ 	.short	0                               # Flags
+ 	.asciz	"overlapped_subfield_ranges"
+ 	.p2align	2
+.Ltmp103:
+ 	.cv_def_range	 .L34 .L36, subfield_reg, 3, 0
+ 	.cv_def_range	 .L35 .L37, subfield_reg, 17, 4
+ 	.cv_def_range	 .L37 .L39,  reg_rel, 1, 1, 4
+ 	.short	.Ltmp105-.Ltmp104
+# CHECK:      (lldb) image lookup -a 0x140001034 -v
+# CHECK:          LineEntry: [0x0000000140001034-0x000000014000103b): C:\src\test\a.cpp:1001
+# CHECK-NEXT:      Variable: id = {{.*}}, name = "overlapped_subfield_ranges", type = "S1", valid ranges = <block>, location = [0x0000000140001034, 0x0000000140001035) -> DW_OP_regx 0x3f, DW_OP_piece 0x1, DW_OP_piece 0x7
+# CHECK-EMPTY:
+# CHECK:      (lldb) image lookup -a 0x140001035 -v
+# CHECK:          LineEntry: [0x0000000140001034-0x000000014000103b): C:\src\test\a.cpp:1001
+# CHECK-NEXT:      Variable: id = {{.*}}, name = "overlapped_subfield_ranges", type = "S1", valid ranges = <block>, location = [0x0000000140001035, 0x0000000140001036) -> DW_OP_regx 0x3f, DW_OP_piece 0x1, DW_OP_piece 0x3, DW_OP_reg24 XMM7, DW_OP_piece 0x4
+# CHECK-EMPTY:
+# CHECK:      (lldb) image lookup -a 0x140001036 -v
+# CHECK:          LineEntry: [0x0000000140001034-0x000000014000103b): C:\src\test\a.cpp:1001
+# CHECK-NEXT:      Variable: id = {{.*}}, name = "overlapped_subfield_ranges", type = "S1", valid ranges = <block>, location = [0x0000000140001036, 0x0000000140001037) -> DW_OP_piece 0x4, DW_OP_reg24 XMM7, DW_OP_piece 0x4
+# CHECK-EMPTY:
+# CHECK:      (lldb) image lookup -a 0x140001037 -v
+# CHECK:          LineEntry: [0x0000000140001034-0x000000014000103b): C:\src\test\a.cpp:1001
+# CHECK-NEXT:      Variable: id = {{.*}}, name = "overlapped_subfield_ranges", type = "S1", valid ranges = <block>, location = [0x0000000140001037, 0x0000000140001039) -> DW_OP_bregx 0x3c +4, DW_OP_piece 0x1, DW_OP_piece 0x7
+# CHECK-EMPTY:
+
+# 3. Test overlapped ranges for the whole value.
+.Ltmp104:
+	.short	4414                            # Record kind: S_LOCAL
+	.long	4109                            # TypeIndex
+	.short	0                               # Flags
+	.asciz	"overlapped_ranges_2"
+	.p2align	2
+.Ltmp105:
+	.cv_def_range	.L3b .L3d, reg, 331
+	.cv_def_range	.L3c .L3e, reg, 330
+	.cv_def_range	.L3f .L44, reg, 339
+	.cv_def_range   .L41 .L43, reg, 328
+	.short	.Ltmp107-.Ltmp106
+# CHECK:      (lldb) image lookup -a 0x14000103b -v
+# CHECK:          LineEntry: [0x000000014000103b-0x0000000140001045): C:\src\test\a.cpp:1002
+# CHECK-NEXT:      Variable: id = {{.*}}, name = "overlapped_ranges_2", type = "S1", valid ranges = <block>, location = [0x000000014000103b, 0x000000014000103c) -> DW_OP_reg3 RBX
+# CHECK-EMPTY:
+# CHECK:      (lldb) image lookup -a 0x14000103d -v
+# CHECK:          LineEntry: [0x000000014000103b-0x0000000140001045): C:\src\test\a.cpp:1002
+# CHECK-NEXT:      Variable: id = {{.*}}, name = "overlapped_ranges_2", type = "S1", valid ranges = <block>, location = [0x000000014000103c, 0x000000014000103e) -> DW_OP_reg2 RCX
+# CHECK-EMPTY:
+# CHECK:      (lldb) image lookup -a 0x14000103f -v
+# CHECK:          LineEntry: [0x000000014000103b-0x0000000140001045): C:\src\test\a.cpp:1002
+# CHECK-NEXT:      Variable: id = {{.*}}, name = "overlapped_ranges_2", type = "S1", valid ranges = <block>, location = [0x000000014000103f, 0x0000000140001041) -> DW_OP_reg11 R11
+# CHECK-EMPTY:
+# CHECK:      (lldb) image lookup -a 0x140001041 -v
+# CHECK:          LineEntry: [0x000000014000103b-0x0000000140001045): C:\src\test\a.cpp:1002
+# CHECK-NEXT:      Variable: id = {{.*}}, name = "overlapped_ranges_2", type = "S1", valid ranges = <block>, location = [0x0000000140001041, 0x0000000140001043) -> DW_OP_reg0 RAX
+# CHECK-EMPTY:
+# CHECK:      (lldb) image lookup -a 0x140001043 -v
+# CHECK:          LineEntry: [0x000000014000103b-0x0000000140001045): C:\src\test\a.cpp:1002
+# CHECK-NEXT:      Variable: id = {{.*}}, name = "overlapped_ranges_2", type = "S1", valid ranges = <block>, location = [0x0000000140001043, 0x0000000140001044) -> DW_OP_reg11 R11
+# CHECK-EMPTY:
+
+# 4. Test overlapped ranges for both subfield and whole value.
+.Ltmp106:
+	.short	4414                            # Record kind: S_LOCAL
+	.long	4109                            # TypeIndex
+	.short	0                               # Flags
+	.asciz	"overlapped_ranges_3"
+	.p2align	2
+.Ltmp107:
+	# The following two lines result:
+	# [.L45, .L46) -> value at offset 0 is at reg 3.
+	# [.L46, .L49) -> value at offset 0 is at reg 3 and value at offset 4 is at reg 17.
+	# [.L49, .L4a) -> value at offset 4 is at reg 17.
+	.cv_def_range	.L46 .L4a, subfield_reg, 17, 4
+	.cv_def_range	.L45 .L49, subfield_reg, 3, 0
+	# The following overwrites range [.L47, .L48) and [.L49 .L4a) because whole
+	# value location is preferred over composited value locations.
+	.cv_def_range	.L47 .L48, reg, 331
+	.cv_def_range	.L49 .L4a, reg, 328
+	# For the same reason, reg 330 wins in following example.
+	.cv_def_range   .L4b .L4e, reg, 330
+	.cv_def_range	.L4b .L4d, subfield_reg, 17, 4
+	.cv_def_range	.L4c .L4e, subfield_reg, 3, 0
+ 	.short 2
+ 	.short	4431                            # Record kind: S_PROC_ID_END
+# CHECK:      (lldb) image lookup -a 0x140001045 -v
+# CHECK:          LineEntry: [0x0000000140001045-0x000000014000104f): C:\src\test\a.cpp:1003
+# CHECK-NEXT:      Variable: id = {{.*}}, name = "overlapped_ranges_3", type = "S1", valid ranges = <block>, location = [0x0000000140001045, 0x0000000140001046) -> DW_OP_regx 0x3f, DW_OP_piece 0x1, DW_OP_piece 0x7
+# CHECK-EMPTY:
+# CHECK:      (lldb) image lookup -a 0x140001046 -v
+# CHECK:          LineEntry: [0x0000000140001045-0x000000014000104f): C:\src\test\a.cpp:1003
+# CHECK-NEXT:      Variable: id = {{.*}}, name = "overlapped_ranges_3", type = "S1", valid ranges = <block>, location = [0x0000000140001046, 0x0000000140001047) -> DW_OP_regx 0x3f, DW_OP_piece 0x1, DW_OP_piece 0x3, DW_OP_reg24 XMM7, DW_OP_piece 0x4
+# CHECK-EMPTY:
+# CHECK:      (lldb) image lookup -a 0x140001047 -v
+# CHECK:          LineEntry: [0x0000000140001045-0x000000014000104f): C:\src\test\a.cpp:1003
+# CHECK-NEXT:      Variable: id = {{.*}}, name = "overlapped_ranges_3", type = "S1", valid ranges = <block>, location = [0x0000000140001047, 0x0000000140001048) -> DW_OP_reg3 RBX
+# CHECK-EMPTY:
+# CHECK:      (lldb) image lookup -a 0x140001048 -v
+# CHECK:          LineEntry: [0x0000000140001045-0x000000014000104f): C:\src\test\a.cpp:1003
+# CHECK-NEXT:      Variable: id = {{.*}}, name = "overlapped_ranges_3", type = "S1", valid ranges = <block>, location = [0x0000000140001048, 0x0000000140001049) -> DW_OP_regx 0x3f, DW_OP_piece 0x1, DW_OP_piece 0x3, DW_OP_reg24 XMM7, DW_OP_piece 0x4
+# CHECK-EMPTY:
+# CHECK:      (lldb) image lookup -a 0x140001049 -v
+# CHECK:          LineEntry: [0x0000000140001045-0x000000014000104f): C:\src\test\a.cpp:1003
+# CHECK-NEXT:      Variable: id = {{.*}}, name = "overlapped_ranges_3", type = "S1", valid ranges = <block>, location = [0x0000000140001049, 0x000000014000104a) -> DW_OP_reg0 RAX
+# CHECK-EMPTY:
+# CHECK:      (lldb) image lookup -a 0x14000104a -v
+# CHECK:          LineEntry: [0x0000000140001045-0x000000014000104f): C:\src\test\a.cpp:1003
+# CHECK-EMPTY:
+# CHECK:      (lldb) image lookup -a 0x14000104b -v
+# CHECK:          LineEntry: [0x0000000140001045-0x000000014000104f): C:\src\test\a.cpp:1003
+# CHECK-NEXT:      Variable: id = {{.*}}, name = "overlapped_ranges_3", type = "S1", valid ranges = <block>, location = [0x000000014000104b, 0x000000014000104e) -> DW_OP_reg2 RCX
+# CHECK-EMPTY:
+# CHECK:      (lldb) image lookup -a 0x14000104c -v
+# CHECK:          LineEntry: [0x0000000140001045-0x000000014000104f): C:\src\test\a.cpp:1003
+# CHECK-NEXT:      Variable: id = {{.*}}, name = "overlapped_ranges_3", type = "S1", valid ranges = <block>, location = [0x000000014000104b, 0x000000014000104e) -> DW_OP_reg2 RCX
+# CHECK-EMPTY:
+
 .Ltmp26:
 	.p2align	2
 	.cv_linetable	1, main, .Lfunc_end1
@@ -452,25 +661,38 @@
 	.byte	243
 	.byte	242
 	.byte	241
-	# StringId (0x100C)
-	.short	0x12                            # Record length
-	.short	0x1605                          # Record kind: LF_STRING_ID
-	.long	0x0                             # Id
-	.asciz	"C:\\src\\test"                 # StringData
-	# StringId (0x100D)
-	.short	0xe                             # Record length
-	.short	0x1605                          # Record kind: LF_STRING_ID
-	.long	0x0                             # Id
-	.asciz	"a.cpp"                         # StringData
-	.byte	242
-	.byte	241
+	# Manually created debug info for testing purpose, FieldList (0x100C) and Struct (0x100D)
+	# FieldList (0x100C)
+	.short	0x1a                            # Record length
+	.short	0x1203                          # Record kind: LF_FIELDLIST
+	.short	0x150d                          # Member kind: DataMember ( LF_MEMBER )
+	.short	0x3                             # Attrs: Public
+	.long	0x70                            # Type: char
+	.short	0x0                             # FieldOffset
+	.asciz	"c"                             # Name
+	.short	0x150d                          # Member kind: DataMember ( LF_MEMBER )
+	.short	0x3                             # Attrs: Public
+	.long	0x74                            # Type: int
+	.short	0x4                             # FieldOffset
+	.asciz	"i"                             # Name
+	# Struct (0x100D)
+	.short	0x20                            # Record length
+	.short	0x1505                          # Record kind: LF_STRUCTURE
+	.short	0x2                             # MemberCount
+	.short	0x200                           # Properties ( HasUniqueName (0x200) )
+	.long	0x100c                          # FieldList: <field list>
+	.long	0x0                             # DerivedFrom
+	.long	0x0                             # VShape
+	.short	0x8                             # SizeOf
+	.asciz	"S1"                            # Name
+	.asciz	".?AUS1@@"                      # LinkageName
 	# BuildInfo (0x100E)
 	.short	0x1a                            # Record length
 	.short	0x1603                          # Record kind: LF_BUILDINFO
-	.short	0x5                             # NumArgs
-	.long	0x100c                          # Argument: C:\src\test
+	.short	0x1                             # NumArgs
+	.long	0x0                             # Argument
+	.long	0x0                             # Argument
 	.long	0x0                             # Argument
-	.long	0x100d                          # Argument: a.cpp
 	.long	0x0                             # Argument
 	.long	0x0                             # Argument
 	.byte	242
Index: lldb/test/Shell/SymbolFile/NativePDB/inline_sites.test
===================================================================
--- lldb/test/Shell/SymbolFile/NativePDB/inline_sites.test
+++ lldb/test/Shell/SymbolFile/NativePDB/inline_sites.test
@@ -52,13 +52,17 @@
 #CHECK: (lldb) b a.cpp:4
 #CHECK: Breakpoint 13: where = {{.*}}`main + 61 at a.cpp:4, address = 0x000000014000103d
 
+# FIXME: The following variable location have wrong register numbers due to
+# https://github.com/llvm/llvm-project/issues/53575. Fix them after resolving
+# the issue.
+
 # CEHCK-LABEL: (lldb) image lookup -a 0x140001003 -v
 # CHECK:       Summary: {{.*}}`main + 3 at a.cpp:2
 # CHECK:       Function: id = {{.*}}, name = "main", range = [0x0000000140001000-0x0000000140001046)
 # CHECK:       Blocks: id = {{.*}}, range = [0x140001000-0x140001046)
 # CHECK:       LineEntry: [0x0000000140001000-0x0000000140001004): /tmp/a.cpp:2
-# CHECK-NEXT:  Variable: id = {{.*}}, name = "argc", type = "int", valid ranges = [0x0000000140001000-0x000000014000102d)
-# CHECK-NEXT:  Variable: id = {{.*}}, name = "argv", type = "char **", valid ranges = [0x0000000140001000-0x0000000140001045)
+# CHECK-NEXT:  Variable: id = {{.*}}, name = "argc", type = "int", valid ranges = <block>, location = [0x0000000140001000, 0x000000014000102d) -> DW_OP_reg26 XMM9
+# CHECK-NEXT:  Variable: id = {{.*}}, name = "argv", type = "char **", valid ranges = <block>, location = [0x0000000140001000, 0x0000000140001045) -> DW_OP_reg3 RBX
 
 # CEHCK-LABEL: (lldb) image lookup -a 0x140001004 -v
 # CHECK:       Summary: {{.*}}`main + 4 [inlined] Namespace1::foo at a.h:5
@@ -67,10 +71,10 @@
 # CHECK:         Blocks: id = {{.*}}, range = [0x140001000-0x140001046)
 # CHECK-NEXT:            id = {{.*}}, ranges = [0x140001004-0x140001039)[0x14000103f-0x140001046), name = "Namespace1::foo", decl = a.h:4
 # CHECK:       LineEntry: [0x0000000140001004-0x000000014000100c): /tmp/a.h:5
-# CHECK-NEXT:  Variable: id = {{.*}}, name = "foo_local", type = "int", valid ranges = [0x0000000140001004-0x0000000140001039)
-# CHECK-NEXT:  Variable: id = {{.*}}, name = "argc", type = "int", valid ranges = [0x0000000140001000-0x000000014000102d)
-# CHECK-NEXT:  Variable: id = {{.*}}, name = "argv", type = "char **", valid ranges = [0x0000000140001000-0x0000000140001045)
-# CHECK-NEXT:  Variable: id = {{.*}}, name = "main_local", type = "int", valid ranges = [0x0000000140001004-0x0000000140001046)
+# CHECK-NEXT:  Variable: id = {{.*}}, name = "foo_local", type = "int", valid ranges = <block>, location = [0x0000000140001004, 0x0000000140001039) -> DW_OP_breg7 RSP+44
+# CHECK-NEXT:  Variable: id = {{.*}}, name = "argc", type = "int", valid ranges = <block>, location = [0x0000000140001000, 0x000000014000102d) -> DW_OP_reg26 XMM9
+# CHECK-NEXT:  Variable: id = {{.*}}, name = "argv", type = "char **", valid ranges = <block>, location = [0x0000000140001000, 0x0000000140001045) -> DW_OP_reg3 RBX
+# CHECK-NEXT:  Variable: id = {{.*}}, name = "main_local", type = "int", valid ranges = <block>, location = [0x0000000140001004, 0x0000000140001046) -> DW_OP_breg7 RSP+48
 
 # CEHCK-LABEL: (lldb) image lookup -a 0x140001010 -v
 # CHECK:       Summary: {{.*}}`main + 16 [inlined] Namespace1::foo + 12 at a.h:7
@@ -79,10 +83,10 @@
 # CHECK:         Blocks: id = {{.*}}, range = [0x140001000-0x140001046)
 # CHECK-NEXT:            id = {{.*}}, ranges = [0x140001004-0x140001039)[0x14000103f-0x140001046), name = "Namespace1::foo", decl = a.h:4
 # CHECK:       LineEntry: [0x0000000140001010-0x0000000140001018): /tmp/a.h:7
-# CHECK-NEXT:  Variable: id = {{.*}}, name = "foo_local", type = "int", valid ranges = [0x0000000140001004-0x0000000140001039)
-# CHECK-NEXT:  Variable: id = {{.*}}, name = "argc", type = "int", valid ranges = [0x0000000140001000-0x000000014000102d)
-# CHECK-NEXT:  Variable: id = {{.*}}, name = "argv", type = "char **", valid ranges = [0x0000000140001000-0x0000000140001045)
-# CHECK-NEXT:  Variable: id = {{.*}}, name = "main_local", type = "int", valid ranges = [0x0000000140001004-0x0000000140001046)
+# CHECK-NEXT:  Variable: id = {{.*}}, name = "foo_local", type = "int", valid ranges = <block>, location = [0x0000000140001004, 0x0000000140001039) -> DW_OP_breg7 RSP+44
+# CHECK-NEXT:  Variable: id = {{.*}}, name = "argc", type = "int", valid ranges = <block>, location = [0x0000000140001000, 0x000000014000102d) -> DW_OP_reg26 XMM9
+# CHECK-NEXT:  Variable: id = {{.*}}, name = "argv", type = "char **", valid ranges = <block>, location = [0x0000000140001000, 0x0000000140001045) -> DW_OP_reg3 RBX
+# CHECK-NEXT:  Variable: id = {{.*}}, name = "main_local", type = "int", valid ranges = <block>, location = [0x0000000140001004, 0x0000000140001046) -> DW_OP_breg7 RSP+48
 
 # CEHCK-LABEL: (lldb) image lookup -a 0x14000101c -v
 # CHECK:       Summary: {{.*}}`main + 28 [inlined] Class1::bar at b.h:5
@@ -93,12 +97,12 @@
 # CHECK-NEXT:            id = {{.*}}, ranges = [0x140001004-0x140001039)[0x14000103f-0x140001046), name = "Namespace1::foo", decl = a.h:4
 # CHECK-NEXT:            id = {{.*}}, range = [0x14000101c-0x140001039), name = "Class1::bar", decl = b.h:4
 # CHECK:       LineEntry: [0x000000014000101c-0x0000000140001022): /tmp/b.h:5
-# CHECK-NEXT:  Variable: id = {{.*}}, name = "x", type = "int", valid ranges = [0x000000014000101c-0x000000014000101e)
-# CHECK-NEXT:  Variable: id = {{.*}}, name = "bar_local", type = "int", valid ranges = [0x000000014000101c-0x0000000140001039)
-# CHECK-NEXT:  Variable: id = {{.*}}, name = "foo_local", type = "int", valid ranges = [0x0000000140001004-0x0000000140001039)
-# CHECK-NEXT:  Variable: id = {{.*}}, name = "argc", type = "int", valid ranges = [0x0000000140001000-0x000000014000102d)
-# CHECK-NEXT:  Variable: id = {{.*}}, name = "argv", type = "char **", valid ranges = [0x0000000140001000-0x0000000140001045)
-# CHECK-NEXT:  Variable: id = {{.*}}, name = "main_local", type = "int", valid ranges = [0x0000000140001004-0x0000000140001046)
+# CHECK-NEXT:  Variable: id = {{.*}}, name = "x", type = "int", valid ranges = <block>, location = [0x000000014000101c, 0x000000014000101e) -> DW_OP_reg24 XMM7
+# CHECK-NEXT:  Variable: id = {{.*}}, name = "bar_local", type = "int", valid ranges = <block>, location = [0x000000014000101c, 0x0000000140001039) -> DW_OP_breg7 RSP+52
+# CHECK-NEXT:  Variable: id = {{.*}}, name = "foo_local", type = "int", valid ranges = <block>, location = [0x0000000140001004, 0x0000000140001039) -> DW_OP_breg7 RSP+44
+# CHECK-NEXT:  Variable: id = {{.*}}, name = "argc", type = "int", valid ranges = <block>, location = [0x0000000140001000, 0x000000014000102d) -> DW_OP_reg26 XMM9
+# CHECK-NEXT:  Variable: id = {{.*}}, name = "argv", type = "char **", valid ranges = <block>, location = [0x0000000140001000, 0x0000000140001045) -> DW_OP_reg3 RBX
+# CHECK-NEXT:  Variable: id = {{.*}}, name = "main_local", type = "int", valid ranges = <block>, location = [0x0000000140001004, 0x0000000140001046) -> DW_OP_breg7 RSP+48
 
 # CEHCK-LABEL: (lldb) image lookup -a 0x14000102a -v
 # CHECK:       Summary: {{.*}}`main + 42 [inlined] Namespace2::Class2::func at c.h:5
@@ -111,21 +115,21 @@
 # CHECK-NEXT:            id = {{.*}}, range = [0x14000101c-0x140001039), name = "Class1::bar", decl = b.h:4
 # CHECK-NEXT:            id = {{.*}}, range = [0x14000102a-0x140001039), name = "Namespace2::Class2::func", decl = c.h:4
 # CHECK:       LineEntry: [0x000000014000102a-0x0000000140001031): /tmp/c.h:5
-# CHECK-NEXT:  Variable: id = {{.*}}, name = "x", type = "int", valid ranges = [0x000000014000102a-0x0000000140001039)
-# CHECK-NEXT:  Variable: id = {{.*}}, name = "func_local", type = "int", valid ranges = [0x000000014000102a-0x0000000140001039)
-# CHECK-NEXT:  Variable: id = {{.*}}, name = "bar_local", type = "int", valid ranges = [0x000000014000101c-0x0000000140001039)
-# CHECK-NEXT:  Variable: id = {{.*}}, name = "foo_local", type = "int", valid ranges = [0x0000000140001004-0x0000000140001039)
-# CHECK-NEXT:  Variable: id = {{.*}}, name = "argc", type = "int", valid ranges = [0x0000000140001000-0x000000014000102d)
-# CHECK-NEXT:  Variable: id = {{.*}}, name = "argv", type = "char **", valid ranges = [0x0000000140001000-0x0000000140001045)
-# CHECK-NEXT:  Variable: id = {{.*}}, name = "main_local", type = "int", valid ranges = [0x0000000140001004-0x0000000140001046)
+# CHECK-NEXT:  Variable: id = {{.*}}, name = "x", type = "int", valid ranges = <block>, location = [0x000000014000102a, 0x0000000140001039) -> DW_OP_reg24 XMM7
+# CHECK-NEXT:  Variable: id = {{.*}}, name = "func_local", type = "int", valid ranges = <block>, location = [0x000000014000102a, 0x0000000140001039) -> DW_OP_breg7 RSP+48
+# CHECK-NEXT:  Variable: id = {{.*}}, name = "bar_local", type = "int", valid ranges = <block>, location = [0x000000014000101c, 0x0000000140001039) -> DW_OP_breg7 RSP+52
+# CHECK-NEXT:  Variable: id = {{.*}}, name = "foo_local", type = "int", valid ranges = <block>, location = [0x0000000140001004, 0x0000000140001039) -> DW_OP_breg7 RSP+44
+# CHECK-NEXT:  Variable: id = {{.*}}, name = "argc", type = "int", valid ranges = <block>, location = [0x0000000140001000, 0x000000014000102d) -> DW_OP_reg26 XMM9
+# CHECK-NEXT:  Variable: id = {{.*}}, name = "argv", type = "char **", valid ranges = <block>, location = [0x0000000140001000, 0x0000000140001045) -> DW_OP_reg3 RBX
+# CHECK-NEXT:  Variable: id = {{.*}}, name = "main_local", type = "int", valid ranges = <block>, location = [0x0000000140001004, 0x0000000140001046) -> DW_OP_breg7 RSP+48
 
 # CEHCK-LABEL: (lldb) image lookup -a 0x140001039 -v
 # CHECK:       Summary: {{.*}}`main + 57 at a.cpp:3
 # CHECK:       Function: id = {{.*}}, name = "main", range = [0x0000000140001000-0x0000000140001046)
 # CHECK:         Blocks: id = {{.*}}, range = [0x140001000-0x140001046)
 # CHECK:       LineEntry: [0x0000000140001039-0x000000014000103d): /tmp/a.cpp:3
-# CHECK-NEXT:  Variable: id = {{.*}}, name = "argv", type = "char **", valid ranges = [0x0000000140001000-0x0000000140001045)
-# CHECK-NEXT:  Variable: id = {{.*}}, name = "main_local", type = "int", valid ranges = [0x0000000140001004-0x0000000140001046)
+# CHECK-NEXT:  Variable: id = {{.*}}, name = "argv", type = "char **", valid ranges = <block>, location = [0x0000000140001000, 0x0000000140001045) -> DW_OP_reg3 RBX
+# CHECK-NEXT:  Variable: id = {{.*}}, name = "main_local", type = "int", valid ranges = <block>, location = [0x0000000140001004, 0x0000000140001046) -> DW_OP_breg7 RSP+48
 
 # CEHCK-LABEL: (lldb) image lookup -a 0x140001044 -v
 # CHECK:       Summary: {{.*}}`main + 68 [inlined] Namespace1::foo + 5 at a.h:8
@@ -134,10 +138,10 @@
 # CHECK:         Blocks: id = {{.*}}, range = [0x140001000-0x140001046)
 # CHECK-NEXT:            id = {{.*}}, ranges = [0x140001004-0x140001039)[0x14000103f-0x140001046), name = "Namespace1::foo", decl = a.h:4
 # CHECK:       LineEntry: [0x0000000140001044-0x0000000140001046): /tmp/a.h:8
-# CHECK-NEXT:  Variable: id = {{.*}}, name = "foo_local", type = "int", valid ranges = [0x0000000140001044-0x0000000140001046)
-# CHECK-NEXT:  Variable: id = {{.*}}, name = "argc", type = "int", valid ranges = [0x0000000140001044-0x0000000140001045)
-# CHECK-NEXT:  Variable: id = {{.*}}, name = "argv", type = "char **", valid ranges = [0x0000000140001000-0x0000000140001045)
-# CHECK-NEXT:  Variable: id = {{.*}}, name = "main_local", type = "int", valid ranges = [0x0000000140001004-0x0000000140001046)
+# CHECK-NEXT:  Variable: id = {{.*}}, name = "foo_local", type = "int", valid ranges = <block>, location = [0x0000000140001044, 0x0000000140001046) -> DW_OP_breg7 RSP+44
+# CHECK-NEXT:  Variable: id = {{.*}}, name = "argc", type = "int", valid ranges = <block>, location = [0x0000000140001044, 0x0000000140001045) -> DW_OP_reg26 XMM9
+# CHECK-NEXT:  Variable: id = {{.*}}, name = "argv", type = "char **", valid ranges = <block>, location = [0x0000000140001000, 0x0000000140001045) -> DW_OP_reg3 RBX
+# CHECK-NEXT:  Variable: id = {{.*}}, name = "main_local", type = "int", valid ranges = <block>, location = [0x0000000140001004, 0x0000000140001046) -> DW_OP_breg7 RSP+48
 
 # CHECK-LABEL: (lldb) target modules dump ast
 # CHECK-NEXT:  Dumping clang ast for 1 modules.
Index: lldb/test/Shell/SymbolFile/NativePDB/Inputs/local-variables-registers.lldbinit
===================================================================
--- lldb/test/Shell/SymbolFile/NativePDB/Inputs/local-variables-registers.lldbinit
+++ lldb/test/Shell/SymbolFile/NativePDB/Inputs/local-variables-registers.lldbinit
@@ -8,4 +8,24 @@
 image lookup -a 0x14000101e -v
 image lookup -a 0x14000102c -v
 
+image lookup -a 0x140001031 -v
+image lookup -a 0x140001032 -v
+image lookup -a 0x140001033 -v
+image lookup -a 0x140001034 -v
+image lookup -a 0x140001035 -v
+image lookup -a 0x140001036 -v
+image lookup -a 0x140001037 -v
+image lookup -a 0x14000103b -v
+image lookup -a 0x14000103d -v
+image lookup -a 0x14000103f -v
+image lookup -a 0x140001041 -v
+image lookup -a 0x140001043 -v
+image lookup -a 0x140001045 -v
+image lookup -a 0x140001046 -v
+image lookup -a 0x140001047 -v
+image lookup -a 0x140001048 -v
+image lookup -a 0x140001049 -v
+image lookup -a 0x14000104a -v
+image lookup -a 0x14000104b -v
+image lookup -a 0x14000104c -v
 exit
Index: lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
===================================================================
--- lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
+++ lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
@@ -1702,9 +1702,13 @@
   func_block->GetStartAddress(addr);
   VariableInfo var_info =
       GetVariableLocationInfo(*m_index, var_id, *func_block, module);
-  if (!var_info.location || !var_info.ranges)
+  if (!var_info.location || var_info.location->GetSize() == 0)
     return nullptr;
-
+  Function *func = func_block->CalculateSymbolContextFunction();
+  if (!func)
+    return VariableSP();
+  var_info.location->SetFuncFileAddress(
+      func->GetAddressRange().GetBaseAddress().GetFileAddress());
   CompilandIndexItem *cii = m_index->compilands().GetCompiland(var_id.modi);
   CompUnitSP comp_unit_sp = GetOrCreateCompileUnit(*cii);
   TypeSP type_sp = GetOrCreateType(var_info.type);
@@ -1720,11 +1724,10 @@
   bool artificial = false;
   bool location_is_constant_data = false;
   bool static_member = false;
-  DWARFExpressionList locaiton_list = DWARFExpressionList(
-      module, *var_info.location, nullptr);
+  Variable::RangeList scope_ranges;
   VariableSP var_sp = std::make_shared<Variable>(
       toOpaqueUid(var_id), name.c_str(), name.c_str(), sftype, var_scope,
-      &block, *var_info.ranges, &decl, locaiton_list, external, artificial,
+      &block, scope_ranges, &decl, *var_info.location, external, artificial,
       location_is_constant_data, static_member);
   if (!is_param)
     m_ast->GetOrCreateVariableDecl(scope_id, var_id);
Index: lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.h
===================================================================
--- lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.h
+++ lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.h
@@ -103,8 +103,7 @@
 struct VariableInfo {
   llvm::StringRef name;
   llvm::codeview::TypeIndex type;
-  llvm::Optional<DWARFExpression> location;
-  llvm::Optional<Variable::RangeList> ranges;
+  llvm::Optional<DWARFExpressionList> location;
   bool is_param;
 };
 
Index: lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp
===================================================================
--- lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp
+++ lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp
@@ -29,6 +29,8 @@
 using namespace llvm::codeview;
 using namespace llvm::pdb;
 
+// The returned range list is guaranteed to be sorted and no overlaps between
+// adjacent ranges because fields in LocalVariableAddrGap are unsigned integers.
 static Variable::RangeList
 MakeRangeList(const PdbIndex &index, const LocalVariableAddrRange &range,
               llvm::ArrayRef<LocalVariableAddrGap> gaps) {
@@ -53,20 +55,216 @@
 
 namespace {
 struct FindMembersSize : public TypeVisitorCallbacks {
-  FindMembersSize(
-      std::map<uint64_t, std::pair<RegisterId, uint32_t>> &members_info,
-      TpiStream &tpi)
-      : members_info(members_info), tpi(tpi) {}
-  std::map<uint64_t, std::pair<RegisterId, uint32_t>> &members_info;
+  FindMembersSize(uint64_t base_offset,
+                  std::map<uint64_t, size_t> &offset_to_size, TpiStream &tpi)
+      : base_offset(base_offset), offset_to_size(offset_to_size), tpi(tpi) {}
+  uint64_t base_offset;
+  std::map<uint64_t, size_t> &offset_to_size;
   TpiStream &tpi;
+
+  static bool GetMemberSizesForUdt(TypeIndex index, llvm::pdb::TpiStream &tpi,
+                            uint64_t base_offset,
+                            std::map<uint64_t, size_t> &offset_to_size) {
+    if (index.isSimple())
+      return true;
+    if (IsForwardRefUdt(index, tpi)) {
+      auto expected_full_ti = tpi.findFullDeclForForwardRef(index);
+      if (!expected_full_ti) {
+        llvm::consumeError(expected_full_ti.takeError());
+        return false;
+      }
+      index = *expected_full_ti;
+    }
+    CVType cvt = tpi.getType(index);
+    switch (cvt.kind()) {
+    case LF_MODIFIER:
+      return GetMemberSizesForUdt({LookThroughModifierRecord(cvt)}, tpi,
+                                  base_offset, offset_to_size);
+    case LF_ENUM:
+    case LF_CLASS:
+    case LF_STRUCTURE:
+    case LF_INTERFACE:
+    case LF_UNION: {
+      TagRecord tag_record = CVTagRecord::create(cvt).asTag();
+      CVType field_list_cvt = tpi.getType(tag_record.FieldList);
+      FieldListRecord field_list;
+      if (llvm::Error error = TypeDeserializer::deserializeAs<FieldListRecord>(
+              field_list_cvt, field_list)) {
+        llvm::consumeError(std::move(error));
+        return false;
+      }
+      FindMembersSize find_members_size(base_offset, offset_to_size, tpi);
+      if (llvm::Error err =
+              visitMemberRecordStream(field_list.Data, find_members_size)) {
+        llvm::consumeError(std::move(err));
+        return false;
+      }
+      return true;
+    }
+    default:
+      return true;
+    }
+  }
+
   llvm::Error visitKnownMember(CVMemberRecord &cvr,
                                DataMemberRecord &member) override {
-    members_info.insert(
-        {member.getFieldOffset(),
-         {llvm::codeview::RegisterId::NONE, GetSizeOfType(member.Type, tpi)}});
+    uint64_t offset = base_offset + member.getFieldOffset();
+    size_t size = GetSizeOfType(member.Type, tpi);
+    // In the case of union, use the largest size.
+    if (offset_to_size[offset] < size)
+      offset_to_size[offset] = size;
+    return llvm::Error::success();
+  }
+  llvm::Error visitKnownMember(CVMemberRecord &cvr,
+                               BaseClassRecord &base) override {
+    GetMemberSizesForUdt(base.getBaseType(), tpi, base.getBaseOffset(),
+                         offset_to_size);
+    return llvm::Error::success();
+  }
+  llvm::Error visitKnownMember(CVMemberRecord &cvr,
+                               VirtualBaseClassRecord &base) override {
+    GetMemberSizesForUdt(base.getBaseType(), tpi, base.getVBPtrOffset(),
+                         offset_to_size);
     return llvm::Error::success();
   }
 };
+
+struct MemberLocations {
+  std::map<uint64_t, MemberValLocation> offset_to_location;
+  DWARFExpression expr;
+  bool is_dwarf = false;
+
+  MemberLocations() = default;
+  MemberLocations(const DWARFExpression &expr) : expr(expr), is_dwarf(true) {}
+  MemberLocations(uint64_t offset, const MemberValLocation &member_loc) {
+    insert(offset, member_loc);
+  }
+
+  void insert(uint64_t offset, const MemberValLocation &member_loc) {
+    offset_to_location[offset] = member_loc;
+  }
+
+  struct Comparator {
+  public:
+    bool operator()(const MemberLocations &, const MemberLocations &) const {
+      return false;
+    }
+  };
+};
+
+// A range map with address ranges to a map of pair of offset and locaitons.
+typedef RangeDataVector<lldb::addr_t, lldb::addr_t, MemberLocations, 0,
+                        MemberLocations::Comparator>
+    RangeMap;
+
+void AddMemberLocationRanges(RangeMap &location_map, uint64_t offset,
+                             MemberValLocation member_loc,
+                             const Variable::RangeList &ranges) {
+  RangeMap new_location_map;
+  auto add_overlap_region = [&](lldb::addr_t base, lldb::addr_t end,
+                                RangeMap::Entry *entry) {
+    RangeMap::Entry overlap_region = {base, end - base, entry->data};
+    overlap_region.data.insert(offset, member_loc);
+    new_location_map.Append(overlap_region);
+  };
+
+  for (const auto &range : ranges) {
+    lldb::addr_t base = range.GetRangeBase();
+    lldb::addr_t end = range.GetRangeEnd();
+    uint32_t base_idx = location_map.FindEntryIndexThatContainsOrFollows(base);
+    while (auto *entry = location_map.GetMutableEntryAtIndex(base_idx)) {
+      if (base >= end || entry->base >= end)
+        break;
+      if (entry->data.is_dwarf)
+        base = entry->GetRangeEnd();
+      else {
+        lldb::addr_t entry_end = entry->GetRangeEnd();
+        if (base > entry->base) {
+          add_overlap_region(base, end < entry_end ? end : entry_end, entry);
+          entry->SetRangeEnd(base);
+        } else if (base < entry->base) {
+          new_location_map.Append(
+              {base, entry->base - base, {offset, member_loc}});
+          if (entry_end == end)
+            entry->data.insert(offset, member_loc);
+          else {
+            add_overlap_region(entry->base, end, entry);
+            entry->ShrinkFront(end - entry->base);
+          }
+        } else {
+          if (end < entry_end) {
+            new_location_map.Append({end, entry_end, entry->data});
+            entry->SetRangeEnd(end);
+          }
+          entry->data.insert(offset, member_loc);
+        }
+        base = entry_end;
+      }
+      ++base_idx;
+    }
+    if (base >= end)
+      continue;
+    new_location_map.Append({base, end - base, {offset, member_loc}});
+  }
+  for (const auto &entry : new_location_map)
+    location_map.Append(entry);
+  if (!new_location_map.IsEmpty())
+    location_map.Sort();
+}
+
+void AddDwarfRange(RangeMap &location_map, const DWARFExpression &expr,
+                   const Variable::RangeList &ranges) {
+  if (!expr.IsValid())
+    return;
+  RangeMap new_location_map;
+  for (const auto &range : ranges) {
+    lldb::addr_t base = range.GetRangeBase();
+    lldb::addr_t end = range.GetRangeEnd();
+    uint32_t base_idx = location_map.FindEntryIndexThatContains(base);
+    uint32_t end_idx = location_map.FindEntryIndexThatContains(end - 1);
+    // range is within an entry.
+    if (base_idx == end_idx && base_idx != UINT32_MAX) {
+      auto *entry = location_map.GetMutableEntryAtIndex(base_idx);
+      if (base > entry->base) {
+        new_location_map.Append({entry->base, base - entry->base, entry->data});
+        entry->ShrinkFront(base - entry->base);
+      }
+      if (end == entry->GetRangeEnd())
+        entry->data = expr;
+      else {
+        entry->ShrinkFront(end - base);
+        new_location_map.Append({base, end - base, expr});
+      }
+      continue;
+    }
+    base_idx = location_map.FindEntryIndexThatContainsOrFollows(base);
+    if (auto *entry = location_map.GetMutableEntryAtIndex(base_idx)) {
+      if (entry->Contains(base) && entry->base != base) {
+        entry->SetRangeEnd(base);
+        ++base_idx;
+      }
+    }
+    end_idx = location_map.FindEntryIndexThatContainsOrFollows(end - 1);
+    if (auto *entry = location_map.GetMutableEntryAtIndex(end_idx)) {
+      if (entry->Contains(end - 1)) {
+        if (entry->GetRangeEnd() == end)
+          ++end_idx;
+        else
+          entry->ShrinkFront(end - entry->base);
+      }
+    }
+
+    if (end_idx == UINT32_MAX)
+      end_idx = location_map.GetSize();
+    // Erase existing ranges covered by new range.
+    location_map.Erase(base_idx, end_idx);
+    new_location_map.Append({base, end - base, expr});
+  }
+
+  for (const auto &entry : new_location_map)
+    location_map.Append(entry);
+  location_map.Sort();
+}
 } // namespace
 
 CVTagRecord CVTagRecord::create(CVType type) {
@@ -612,207 +810,182 @@
   if (sym.kind() == S_REGREL32) {
     RegRelativeSym reg(SymbolRecordKind::RegRelativeSym);
     cantFail(SymbolDeserializer::deserializeAs<RegRelativeSym>(sym, reg));
-    result.location =
-        MakeRegRelLocationExpression(reg.Register, reg.Offset, module);
-    result.ranges.emplace();
+    result.location = DWARFExpressionList(
+        module, MakeRegRelLocationExpression(reg.Register, reg.Offset, module),
+        nullptr);
     return result;
   }
 
   if (sym.kind() == S_REGISTER) {
     RegisterSym reg(SymbolRecordKind::RegisterSym);
     cantFail(SymbolDeserializer::deserializeAs<RegisterSym>(sym, reg));
-    result.location = MakeEnregisteredLocationExpression(reg.Register, module);
-    result.ranges.emplace();
+    result.location = DWARFExpressionList(
+        module, MakeEnregisteredLocationExpression(reg.Register, module),
+        nullptr);
     return result;
   }
 
   if (sym.kind() == S_LOCAL) {
     LocalSym local(SymbolRecordKind::LocalSym);
-    cantFail(SymbolDeserializer::deserializeAs<LocalSym>(sym, local));
+    if (llvm::Error error =
+            SymbolDeserializer::deserializeAs<LocalSym>(sym, local)) {
+      llvm::consumeError(std::move(error));
+      return result;
+    }
 
     PdbCompilandSymId loc_specifier_id(var_id.modi,
                                        var_id.offset + sym.RecordData.size());
-    CVSymbol loc_specifier_cvs = index.ReadSymbolRecord(loc_specifier_id);
-    switch(loc_specifier_cvs.kind()) {
-    case S_DEFRANGE_FRAMEPOINTER_REL: {
-      DefRangeFramePointerRelSym loc(
-          SymbolRecordKind::DefRangeFramePointerRelSym);
-      cantFail(SymbolDeserializer::deserializeAs<DefRangeFramePointerRelSym>(
-          loc_specifier_cvs, loc));
-
-      Variable::RangeList ranges = MakeRangeList(index, loc.Range, loc.Gaps);
-
-      PdbCompilandSymId func_scope_id =
-          PdbSymUid(func_block.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());
-
-      RegisterId base_reg =
-          GetBaseFrameRegister(index, frame_proc_id, result.is_param);
-      if (base_reg == RegisterId::NONE)
-        break;
-      if (base_reg == RegisterId::VFRAME) {
-        llvm::StringRef program;
-        if (GetFrameDataProgram(index, ranges, program)) {
-          result.location =
-              MakeVFrameRelLocationExpression(program, loc.Hdr.Offset, module);
-          result.ranges = std::move(ranges);
-        } else {
-          // invalid variable
+    CVSymbol loc_specifier_cvs;
+    // Only used for S_DEFRANGE_FRAMEPOINTER_REL.
+    RegisterId base_reg = RegisterId::NONE;
+    size_t type_size = GetSizeOfType(result.type, index.tpi());
+    // A map from offset of a field in parent to size of the field.
+    std::map<uint64_t, size_t> offset_to_size;
+    // Get the size of each fields if it's udt.
+    if (!FindMembersSize::GetMemberSizesForUdt(result.type, index.tpi(), 0,
+                                               offset_to_size))
+      return result;
+
+    // When overlaps happens, always prefer the one that doesn't split the value
+    // into multiple locations and the location parsed first is perfered.
+    RangeMap location_map;
+
+    // Iterate through all location records after S_LOCAL. They describe the
+    // value of this variable at different locations.
+    bool finished = false;
+    while (!finished) {
+      loc_specifier_cvs = index.ReadSymbolRecord(loc_specifier_id);
+      switch (loc_specifier_cvs.kind()) {
+      case S_DEFRANGE_FRAMEPOINTER_REL: {
+        DefRangeFramePointerRelSym loc(
+            SymbolRecordKind::DefRangeFramePointerRelSym);
+        if (llvm::Error error =
+                SymbolDeserializer::deserializeAs<DefRangeFramePointerRelSym>(
+                    loc_specifier_cvs, loc)) {
+          llvm::consumeError(std::move(error));
+          return result;
         }
-      } else {
-        result.location =
-            MakeRegRelLocationExpression(base_reg, loc.Hdr.Offset, module);
-        result.ranges = std::move(ranges);
+        Variable::RangeList raw_ranges =
+            MakeRangeList(index, loc.Range, loc.Gaps);
+        if (base_reg == RegisterId::NONE) {
+          PdbCompilandSymId func_scope_id =
+              PdbSymUid(func_block.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());
+          base_reg =
+              GetBaseFrameRegister(index, frame_proc_id, result.is_param);
+          if (base_reg == RegisterId::NONE)
+            break;
+        }
+        DWARFExpression expr;
+        if (base_reg == RegisterId::VFRAME) {
+          llvm::StringRef program;
+          if (GetFrameDataProgram(index, raw_ranges, program))
+            expr = MakeVFrameRelLocationExpression(program, loc.Hdr.Offset,
+                                                   module);
+          else {
+            // invalid variable
+          }
+        } else
+          expr = MakeRegRelLocationExpression(base_reg, loc.Hdr.Offset, module);
+        AddDwarfRange(location_map, expr, raw_ranges);
+        break;
       }
-      break;
-    }
-    case 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
+      case S_DEFRANGE_REGISTER: {
+        DefRangeRegisterSym loc(SymbolRecordKind::DefRangeRegisterSym);
+        if (llvm::Error error =
+                SymbolDeserializer::deserializeAs<DefRangeRegisterSym>(
+                    loc_specifier_cvs, loc)) {
+          llvm::consumeError(std::move(error));
+          return result;
         }
-      } else {
-        result.location = MakeRegRelLocationExpression(
-            base_reg, loc.Hdr.BasePointerOffset, module);
-        result.ranges = std::move(ranges);
+        RegisterId reg_id = (RegisterId)(uint16_t)loc.Hdr.Register;
+        Variable::RangeList raw_ranges =
+            MakeRangeList(index, loc.Range, loc.Gaps);
+        DWARFExpression expr =
+            MakeEnregisteredLocationExpression(reg_id, module);
+        AddDwarfRange(location_map, expr, raw_ranges);
+        break;
       }
-      break;
-    }
-    case S_DEFRANGE_REGISTER: {
-      DefRangeRegisterSym loc(SymbolRecordKind::DefRangeRegisterSym);
-      cantFail(SymbolDeserializer::deserializeAs<DefRangeRegisterSym>(
-          loc_specifier_cvs, loc));
-
-      RegisterId base_reg = (RegisterId)(uint16_t)loc.Hdr.Register;
-      result.ranges = MakeRangeList(index, loc.Range, loc.Gaps);
-      result.location = MakeEnregisteredLocationExpression(base_reg, module);
-      break;
-    }
-    case S_DEFRANGE_SUBFIELD_REGISTER: {
-      // A map from offset in parent to pair of register id and size. If the
-      // variable is a simple type, then we don't know the number of subfields.
-      // Otherwise, the size of the map should be greater than or equal to the
-      // number of sub field record.
-      std::map<uint64_t, std::pair<RegisterId, uint32_t>> members_info;
-      bool is_simple_type = result.type.isSimple();
-      if (!is_simple_type) {
-        CVType class_cvt = index.tpi().getType(result.type);
-        TypeIndex class_id = result.type;
-        if (class_cvt.kind() == LF_MODIFIER)
-          class_id = LookThroughModifierRecord(class_cvt);
-        if (IsForwardRefUdt(class_id, index.tpi())) {
-          auto expected_full_ti =
-              index.tpi().findFullDeclForForwardRef(class_id);
-          if (!expected_full_ti) {
-            llvm::consumeError(expected_full_ti.takeError());
-            break;
-          }
-          class_cvt = index.tpi().getType(*expected_full_ti);
+      case S_DEFRANGE_REGISTER_REL: {
+        DefRangeRegisterRelSym loc(SymbolRecordKind::DefRangeRegisterRelSym);
+        if (llvm::Error error =
+                SymbolDeserializer::deserializeAs<DefRangeRegisterRelSym>(
+                    loc_specifier_cvs, loc)) {
+          llvm::consumeError(std::move(error));
+          return result;
         }
-        if (IsTagRecord(class_cvt)) {
-          TagRecord tag_record = CVTagRecord::create(class_cvt).asTag();
-          CVType field_list_cvt = index.tpi().getType(tag_record.FieldList);
-          FieldListRecord field_list;
-          if (llvm::Error error =
-                  TypeDeserializer::deserializeAs<FieldListRecord>(
-                      field_list_cvt, field_list))
-            llvm::consumeError(std::move(error));
-          FindMembersSize find_members_size(members_info, index.tpi());
-          if (llvm::Error err = visitMemberRecordStream(field_list.Data,
-                                                        find_members_size)) {
-            llvm::consumeError(std::move(err));
-            break;
+        Variable::RangeList raw_ranges =
+            MakeRangeList(index, loc.Range, loc.Gaps);
+        RegisterId reg_id = (RegisterId)(uint16_t)loc.Hdr.Register;
+        DWARFExpression expr;
+        if (reg_id == RegisterId::VFRAME) {
+          llvm::StringRef program;
+          if (GetFrameDataProgram(index, raw_ranges, program))
+            expr = MakeVFrameRelLocationExpression(
+                program, loc.Hdr.BasePointerOffset, module);
+          else {
+            // invalid variable
           }
         } else {
-          // TODO: Handle poiner type.
-          break;
+          expr = MakeRegRelLocationExpression(reg_id, loc.Hdr.BasePointerOffset,
+                                              module);
+        }
+        if (expr.IsValid()) {
+          if (loc.hasSpilledUDTMember()) {
+            uint64_t offset = loc.offsetInParent();
+            AddMemberLocationRanges(
+                location_map, offset,
+                {(uint16_t)reg_id, (uint16_t)loc.Hdr.BasePointerOffset, false},
+                raw_ranges);
+          } else
+            AddDwarfRange(location_map, expr, raw_ranges);
         }
+        break;
       }
-
-      size_t member_idx = 0;
-      // Assuming S_DEFRANGE_SUBFIELD_REGISTER is followed only by
-      // S_DEFRANGE_SUBFIELD_REGISTER, need to verify.
-      while (loc_specifier_cvs.kind() == S_DEFRANGE_SUBFIELD_REGISTER) {
-        if (!is_simple_type && member_idx >= members_info.size())
-          break;
-
+      case S_DEFRANGE_SUBFIELD_REGISTER: {
         DefRangeSubfieldRegisterSym loc(
             SymbolRecordKind::DefRangeSubfieldRegisterSym);
-        cantFail(SymbolDeserializer::deserializeAs<DefRangeSubfieldRegisterSym>(
-            loc_specifier_cvs, loc));
-
-        if (result.ranges) {
-          result.ranges = Variable::RangeList::GetOverlaps(
-              *result.ranges, MakeRangeList(index, loc.Range, loc.Gaps));
-        } else {
-          result.ranges = MakeRangeList(index, loc.Range, loc.Gaps);
-          result.ranges->Sort();
+        if (llvm::Error error =
+                SymbolDeserializer::deserializeAs<DefRangeSubfieldRegisterSym>(
+                    loc_specifier_cvs, loc)) {
+          llvm::consumeError(std::move(error));
+          return result;
         }
 
-        if (is_simple_type) {
-          if (members_info.count(loc.Hdr.OffsetInParent)) {
-            // Malformed record.
-            result.ranges->Clear();
-            return result;
-          }
-          members_info[loc.Hdr.OffsetInParent] = {
-              (RegisterId)(uint16_t)loc.Hdr.Register, 0};
-        } else {
-          if (!members_info.count(loc.Hdr.OffsetInParent)) {
-            // Malformed record.
-            result.ranges->Clear();
-            return result;
-          }
-          members_info[loc.Hdr.OffsetInParent].first =
-              (RegisterId)(uint16_t)loc.Hdr.Register;
-        }
-        // Go to next S_DEFRANGE_SUBFIELD_REGISTER.
-        loc_specifier_id = PdbCompilandSymId(
-            loc_specifier_id.modi,
-            loc_specifier_id.offset + loc_specifier_cvs.RecordData.size());
-        loc_specifier_cvs = index.ReadSymbolRecord(loc_specifier_id);
+        Variable::RangeList ranges = MakeRangeList(index, loc.Range, loc.Gaps);
+        AddMemberLocationRanges(location_map, loc.Hdr.OffsetInParent,
+                                {loc.Hdr.Register, 0, true}, ranges);
+        break;
       }
-      // Fix size for simple type.
-      if (is_simple_type) {
-        auto cur = members_info.begin();
-        auto end = members_info.end();
-        auto next = cur;
-        ++next;
-        uint32_t size = 0;
-        while (next != end) {
-          cur->second.second = next->first - cur->first;
-          size += cur->second.second;
-          cur = next++;
-        }
-        cur->second.second =
-            GetTypeSizeForSimpleKind(result.type.getSimpleKind()) - size;
+      // FIXME: Handle other kinds. LLVM only generates the 4 types of records
+      // above. MSVC generates other location types.
+      case S_DEFRANGE:
+      case S_DEFRANGE_SUBFIELD:
+      case S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE:
+        break;
+      default:
+        finished = true;
+        break;
       }
-      result.location =
-          MakeEnregisteredLocationExpressionForClass(members_info, module);
-      break;
+      loc_specifier_id = PdbCompilandSymId(
+          loc_specifier_id.modi,
+          loc_specifier_id.offset + loc_specifier_cvs.RecordData.size());
     }
-    default:
-      // FIXME: Handle other kinds. LLVM only generates the 4 types of records
-      // above.
-      break;
+    result.location = DWARFExpressionList();
+    for (const auto &entry : location_map) {
+      DWARFExpression dwarf_expr =
+          entry.data.is_dwarf ? entry.data.expr
+                              : MakeEnregisteredLocationExpressionForComposite(
+                                    entry.data.offset_to_location,
+                                    offset_to_size, type_size, module);
+
+      result.location->AddExpression(entry.GetRangeBase(), entry.GetRangeEnd(),
+                                     dwarf_expr);
     }
     return result;
   }
Index: lldb/source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.h
===================================================================
--- lldb/source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.h
+++ lldb/source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.h
@@ -26,6 +26,12 @@
 } // namespace llvm
 namespace lldb_private {
 namespace npdb {
+struct MemberValLocation {
+  uint16_t reg_id;
+  uint16_t reg_offset;
+  bool is_at_reg = true;
+};
+
 DWARFExpression
 MakeEnregisteredLocationExpression(llvm::codeview::RegisterId reg,
                                    lldb::ModuleSP module);
@@ -41,9 +47,9 @@
 DWARFExpression MakeConstantLocationExpression(
     llvm::codeview::TypeIndex underlying_ti, llvm::pdb::TpiStream &tpi,
     const llvm::APSInt &constant, lldb::ModuleSP module);
-DWARFExpression MakeEnregisteredLocationExpressionForClass(
-    std::map<uint64_t, std::pair<llvm::codeview::RegisterId, uint32_t>>
-        &members_info,
+DWARFExpression MakeEnregisteredLocationExpressionForComposite(
+    const std::map<uint64_t, MemberValLocation> &offset_to_location,
+    std::map<uint64_t, size_t> &offset_to_size, size_t total_size,
     lldb::ModuleSP module);
 } // namespace npdb
 } // namespace lldb_private
Index: lldb/source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.cpp
===================================================================
--- lldb/source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.cpp
+++ lldb/source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.cpp
@@ -128,33 +128,38 @@
   return result;
 }
 
+static bool MakeRegisterBasedLocationExpressionInternal(
+    Stream &stream, llvm::codeview::RegisterId reg, RegisterKind register_kind,
+    llvm::Optional<int32_t> relative_offset, lldb::ModuleSP module) {
+  uint32_t reg_num = GetRegisterNumber(module->GetArchitecture().GetMachine(),
+                                       reg, register_kind);
+  if (reg_num == LLDB_INVALID_REGNUM)
+    return false;
+
+  if (reg_num > 31) {
+    llvm::dwarf::LocationAtom base =
+        relative_offset ? llvm::dwarf::DW_OP_bregx : llvm::dwarf::DW_OP_regx;
+    stream.PutHex8(base);
+    stream.PutULEB128(reg_num);
+  } else {
+    llvm::dwarf::LocationAtom base =
+        relative_offset ? llvm::dwarf::DW_OP_breg0 : llvm::dwarf::DW_OP_reg0;
+    stream.PutHex8(base + reg_num);
+  }
+
+  if (relative_offset)
+    stream.PutSLEB128(*relative_offset);
+
+  return true;
+}
+
 static DWARFExpression MakeRegisterBasedLocationExpressionInternal(
     llvm::codeview::RegisterId reg, llvm::Optional<int32_t> relative_offset,
     lldb::ModuleSP module) {
   return MakeLocationExpressionInternal(
       module, [&](Stream &stream, RegisterKind &register_kind) -> bool {
-        uint32_t reg_num = GetRegisterNumber(
-            module->GetArchitecture().GetMachine(), reg, register_kind);
-        if (reg_num == LLDB_INVALID_REGNUM)
-          return false;
-
-        if (reg_num > 31) {
-          llvm::dwarf::LocationAtom base = relative_offset
-                                               ? llvm::dwarf::DW_OP_bregx
-                                               : llvm::dwarf::DW_OP_regx;
-          stream.PutHex8(base);
-          stream.PutULEB128(reg_num);
-        } else {
-          llvm::dwarf::LocationAtom base = relative_offset
-                                               ? llvm::dwarf::DW_OP_breg0
-                                               : llvm::dwarf::DW_OP_reg0;
-          stream.PutHex8(base + reg_num);
-        }
-
-        if (relative_offset)
-          stream.PutSLEB128(*relative_offset);
-
-        return true;
+        return MakeRegisterBasedLocationExpressionInternal(
+            stream, reg, register_kind, relative_offset, module);
       });
 }
 
@@ -251,28 +256,43 @@
   return result;
 }
 
-DWARFExpression lldb_private::npdb::MakeEnregisteredLocationExpressionForClass(
-    std::map<uint64_t, std::pair<RegisterId, uint32_t>> &members_info,
+DWARFExpression
+lldb_private::npdb::MakeEnregisteredLocationExpressionForComposite(
+    const std::map<uint64_t, MemberValLocation> &offset_to_location,
+    std::map<uint64_t, size_t> &offset_to_size, size_t total_size,
     lldb::ModuleSP module) {
   return MakeLocationExpressionInternal(
       module, [&](Stream &stream, RegisterKind &register_kind) -> bool {
-        for (auto pair : members_info) {
-          std::pair<RegisterId, uint32_t> member_info = pair.second;
-          if (member_info.first != llvm::codeview::RegisterId::NONE) {
-            uint32_t reg_num =
-                GetRegisterNumber(module->GetArchitecture().GetMachine(),
-                                  member_info.first, register_kind);
-            if (reg_num == LLDB_INVALID_REGNUM)
-              return false;
-            if (reg_num > 31) {
-              stream.PutHex8(llvm::dwarf::DW_OP_regx);
-              stream.PutULEB128(reg_num);
-            } else {
-              stream.PutHex8(llvm::dwarf::DW_OP_reg0 + reg_num);
-            }
+        size_t cur_offset = 0;
+        bool is_simple_type = offset_to_size.empty();
+        // Iterate through offset_to_location because offset_to_size might be
+        // empty if the variable is a simple type.
+        for (const auto &offset_loc : offset_to_location) {
+          if (cur_offset < offset_loc.first) {
+            stream.PutHex8(llvm::dwarf::DW_OP_piece);
+            stream.PutULEB128(offset_loc.first - cur_offset);
+            cur_offset = offset_loc.first;
           }
+          MemberValLocation loc = offset_loc.second;
+          llvm::Optional<int32_t> offset =
+              loc.is_at_reg ? llvm::None
+                            : llvm::Optional<int32_t>(loc.reg_offset);
+          if (!MakeRegisterBasedLocationExpressionInternal(
+                  stream, (RegisterId)loc.reg_id, register_kind, offset,
+                  module))
+            return false;
+          if (!is_simple_type) {
+            stream.PutHex8(llvm::dwarf::DW_OP_piece);
+            stream.PutULEB128(offset_to_size[offset_loc.first]);
+            cur_offset = offset_loc.first + offset_to_size[offset_loc.first];
+          }
+        }
+        // For simple type, it specifies the byte size of the value described by
+        // the previous dwarf expr. For udt, it's the remaining byte size at end
+        // of a struct.
+        if (total_size > cur_offset) {
           stream.PutHex8(llvm::dwarf::DW_OP_piece);
-          stream.PutULEB128(member_info.second);
+          stream.PutULEB128(total_size - cur_offset);
         }
         return true;
       });
Index: lldb/include/lldb/Utility/RangeMap.h
===================================================================
--- lldb/include/lldb/Utility/RangeMap.h
+++ lldb/include/lldb/Utility/RangeMap.h
@@ -49,6 +49,11 @@
 
   void Slide(BaseType slide) { base += slide; }
 
+  void ShrinkFront(S s) {
+    base += s;
+    size -= size > s ? s : size;
+  }
+
   bool Union(const Range &rhs) {
     if (DoesAdjoinOrIntersect(rhs)) {
       auto new_end = std::max<BaseType>(GetRangeEnd(), rhs.GetRangeEnd());
@@ -445,6 +450,13 @@
 
   void Append(const Entry &entry) { m_entries.emplace_back(entry); }
 
+  bool Erase(uint32_t start, uint32_t end) {
+    if (start >= end || end > m_entries.size())
+      return false;
+    m_entries.erase(begin() + start, begin() + end);
+    return true;
+  }
+
   void Sort() {
     if (m_entries.size() > 1)
       std::stable_sort(m_entries.begin(), m_entries.end(),
@@ -621,6 +633,17 @@
     return nullptr;
   }
 
+  uint32_t FindEntryIndexThatContainsOrFollows(B addr) const {
+#ifdef ASSERT_RANGEMAP_ARE_SORTED
+    assert(IsSorted());
+#endif
+    const AugmentedEntry *entry = static_cast<const AugmentedEntry *>(
+        FindEntryThatContainsOrFollows(addr));
+    if (entry)
+      return std::distance(m_entries.begin(), entry);
+    return UINT32_MAX;
+  }
+
   Entry *Back() { return (m_entries.empty() ? nullptr : &m_entries.back()); }
 
   const Entry *Back() const {
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to