int64_t Offset = 0;
const unsigned NumElements = DIExpr->getNumElements();
const auto Elements = DIExpr->getElements();
- unsigned NextElement = 0;
+ unsigned ExpectedDerefIdx = 0;
// Extract the offset.
if (NumElements > 2 && Elements[0] == dwarf::DW_OP_plus_uconst) {
Offset = Elements[1];
- NextElement = 2;
+ ExpectedDerefIdx = 2;
} else if (NumElements > 3 && Elements[0] == dwarf::DW_OP_constu) {
- NextElement = 3;
+ ExpectedDerefIdx = 3;
if (Elements[2] == dwarf::DW_OP_plus)
Offset = Elements[1];
else if (Elements[2] == dwarf::DW_OP_minus)
}
// If that's all there is it means there's no deref.
- if (NextElement >= NumElements)
+ if (ExpectedDerefIdx >= NumElements)
return std::nullopt;
// Check the next element is DW_OP_deref - otherwise this is too complex or
// isn't a deref expression.
- if (Elements[NextElement] != dwarf::DW_OP_deref)
+ if (Elements[ExpectedDerefIdx] != dwarf::DW_OP_deref)
return std::nullopt;
// Check the final operation is either the DW_OP_deref or is a fragment.
- if (NumElements == NextElement + 1)
+ if (NumElements == ExpectedDerefIdx + 1)
return Offset; // Ends with deref.
- else if (NumElements == NextElement + 3 &&
- Elements[NextElement] == dwarf::DW_OP_LLVM_fragment)
+ unsigned ExpectedFragFirstIdx = ExpectedDerefIdx + 1;
+ unsigned ExpectedFragFinalIdx = ExpectedFragFirstIdx + 2;
+ if (NumElements == ExpectedFragFinalIdx + 1 &&
+ Elements[ExpectedFragFirstIdx] == dwarf::DW_OP_LLVM_fragment)
return Offset; // Ends with deref + fragment.
// Don't bother trying to interpret anything more complex.
; INSTRREF: %2:gr64 = nsw ADD64ri8 %1, 2, implicit-def dead $eflags, debug-instr-number 1
; INSTRREF-NEXT: DBG_INSTR_REF ![[VAR]], !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_LLVM_fragment, 64, 64), dbg-instr-ref(1, 0), debug-location
+;; Bits [0, 64) are still stack homed. FIXME, this particular reinstatement is
+;; unnecessary.
+; CHECK-NEXT: DBG_VALUE %stack.0.X, $noreg, ![[VAR]], !DIExpression(DW_OP_deref, DW_OP_LLVM_fragment, 0, 64)
+
source_filename = "test.cpp"
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
call void @llvm.dbg.assign(metadata i32 2, metadata !12, metadata !DIExpression(DW_OP_LLVM_fragment, 64, 32), metadata !31, metadata ptr %c, metadata !DIExpression()), !dbg !19
; CHECK-NEXT: DBG_VALUE %stack.0.nums, $noreg, ![[nums]], !DIExpression(DW_OP_plus_uconst, 8, DW_OP_deref, DW_OP_LLVM_fragment, 64, 32)
tail call void @_Z4stepv(), !dbg !32
+;; Next dbg.assign added by hand to test that the bits [64, 32) have been
+;; correctly tracked as in memory - we know this has worked if
+;; mem-loc-frag-fill reinstates the memory location after this kill-location
+;; for bits [80, 96).
+ call void @llvm.dbg.assign(metadata i32 poison, metadata !12, metadata !DIExpression(DW_OP_LLVM_fragment, 80, 16), metadata !44, metadata ptr poison, metadata !DIExpression()), !dbg !19
+; CHECK: CALL64pcrel32 @_Z4stepv
+; CHECK-NEXT: ADJCALLSTACKUP64
+; CHECK-NEXT: DBG_VALUE $noreg, $noreg, ![[nums]], !DIExpression(DW_OP_LLVM_fragment, 80, 16)
+; CHECK-NEXT: DBG_VALUE %stack.0.nums, $noreg, ![[nums]], !DIExpression(DW_OP_deref, DW_OP_LLVM_fragment, 0, 80)
+ tail call void @_Z4stepv(), !dbg !32
call void @_Z3escP4Nums(ptr noundef nonnull %nums), !dbg !33
ret i32 0, !dbg !35
}
!41 = !DISubroutineType(types: !42)
!42 = !{null, !43}
!43 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !13, size: 64)
+!44 = distinct !DIAssignID()
!1000 = !{i32 7, !"debug-info-assignment-tracking", i1 true}
do.end6: ; preds = %do.cond4
call void @llvm.dbg.assign(metadata i32 3, metadata !21, metadata !DIExpression(DW_OP_LLVM_fragment, 0, 32), metadata !63, metadata ptr %a.addr, metadata !DIExpression()), !dbg !27; VAR:a
- call void @llvm.dbg.assign(metadata i32 0, metadata !21, metadata !DIExpression(DW_OP_LLVM_fragment, 32, 32), metadata !70, metadata ptr %a.addr, metadata !DIExpression()), !dbg !27; VAR:a
+ call void @llvm.dbg.assign(metadata i32 0, metadata !21, metadata !DIExpression(DW_OP_LLVM_fragment, 32, 32), metadata !70, metadata ptr %a.addr, metadata !DIExpression(DW_OP_plus_uconst, 32)), !dbg !27; VAR:a
;call void @llvm.dbg.assign(metadata i32 3, metadata !21, metadata !DIExpression(DW_OP_LLVM_fragment, 32, 32), metadata !81, metadata ptr %a.addr, metadata !DIExpression()), !dbg !27; VAR:a
call void @llvm.dbg.assign(metadata i32 4, metadata !22, metadata !DIExpression(DW_OP_LLVM_fragment, 0, 32), metadata !65, metadata ptr %b.addr, metadata !DIExpression()), !dbg !27 ; VAR:b
call void @llvm.dbg.assign(metadata i32 0, metadata !22, metadata !DIExpression(DW_OP_LLVM_fragment, 32, 32), metadata !71, metadata ptr %b.addr, metadata !DIExpression()), !dbg !27 ; VAR:b
;call void @llvm.dbg.assign(metadata i32 11, metadata !79, metadata !DIExpression(DW_OP_LLVM_fragment, 0, 32), metadata !81, metadata ptr %f.addr, metadata !DIExpression()), !dbg !27 ; VAR:f
ret i32 0, !dbg !53
; CHECK-LABEL: bb.7.do.end6:
+; CHECK-NEXT: DBG_VALUE %stack.0.a.addr, $noreg, ![[a]], !DIExpression(DW_OP_plus_uconst, 32, DW_OP_deref, DW_OP_LLVM_fragment, 32, 32)
; CHECK-NEXT: DBG_VALUE %stack.0.a.addr, $noreg, ![[a]], !DIExpression(DW_OP_deref, DW_OP_LLVM_fragment, 0, 32)
-; CHECK-NEXT: DBG_VALUE %stack.0.a.addr, $noreg, ![[a]], !DIExpression(DW_OP_deref, DW_OP_LLVM_fragment, 32, 32)
; CHECK-NEXT: DBG_VALUE 4, $noreg, ![[b]], !DIExpression(DW_OP_LLVM_fragment, 0, 32)
; CHECK-NEXT: DBG_VALUE %stack.1.b.addr, $noreg, ![[b]], !DIExpression(DW_OP_deref, DW_OP_LLVM_fragment, 32, 32)
; xCHECK-NEXT: XXX ? DBG_VALUE %stack.3.d.addr, $noreg, ![[d]], !DIExpression(DW_OP_deref, DW_OP_LLVM_fragment, 32, 32)