Skip to content

Commit f40e8f1

Browse files
committed
[Assignment Tracking] Ignore stores to a negative offset from an alloca
Fixes crash reported in llvm.org/PR62838. Reviewed By: jryans Differential Revision: https://reviews.llvm.org/D151326
1 parent da836b3 commit f40e8f1

File tree

2 files changed

+97
-1
lines changed

2 files changed

+97
-1
lines changed

llvm/lib/IR/DebugInfo.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1915,7 +1915,8 @@ bool at::calculateFragmentIntersect(
19151915
}
19161916

19171917
/// Collect constant properies (base, size, offset) of \p StoreDest.
1918-
/// Return std::nullopt if any properties are not constants.
1918+
/// Return std::nullopt if any properties are not constants or the
1919+
/// offset from the base pointer is negative.
19191920
static std::optional<AssignmentInfo>
19201921
getAssignmentInfoImpl(const DataLayout &DL, const Value *StoreDest,
19211922
TypeSize SizeInBits) {
@@ -1924,6 +1925,10 @@ getAssignmentInfoImpl(const DataLayout &DL, const Value *StoreDest,
19241925
APInt GEPOffset(DL.getIndexTypeSizeInBits(StoreDest->getType()), 0);
19251926
const Value *Base = StoreDest->stripAndAccumulateConstantOffsets(
19261927
DL, GEPOffset, /*AllowNonInbounds*/ true);
1928+
1929+
if (GEPOffset.isNegative())
1930+
return std::nullopt;
1931+
19271932
uint64_t OffsetInBytes = GEPOffset.getLimitedValue();
19281933
// Check for overflow.
19291934
if (OffsetInBytes == UINT64_MAX)
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
; RUN: llc %s -stop-after=finalize-isel -o - | FileCheck %s --implicit-check-not=DBG_VALUE
2+
3+
;; Check stores to an address computed as a negative offset from an alloca are
4+
;; ignored by the assignment tracking analysis. For this example that should
5+
;; result in no DBG_VALUEs in the while.body.lr.ph branch.
6+
;;
7+
;; See llvm.org/PR62838 for more info.
8+
;;
9+
;; $ clang test.c -O1 -g
10+
;; $ cat tes.c
11+
;; void a(int *p);
12+
;; __attribute__((nodebug)) int b;
13+
;;
14+
;; int main() {
15+
;; int c[1];
16+
;; __attribute__((nodebug)) int d = -1;
17+
;;
18+
;; while (b) {
19+
;; c[0] = 0;
20+
;; c[d] = 0;
21+
;; }
22+
;; a(c);
23+
;; return 0;
24+
;; }
25+
26+
; CHECK: bb.0.entry:
27+
; CHECK-NEXT: successors
28+
; CHECK-NEXT: {{^ *$}}
29+
; CHECK-NEXT: DBG_VALUE %stack.0.c, $noreg, ![[#]], !DIExpression(DW_OP_deref)
30+
31+
; CHECK: bb.2.while.body:
32+
; CHECK-NEXT: successors
33+
; CHECK-NEXT: {{^ *$}}
34+
; CHECK-NEXT: DBG_VALUE 0, $noreg, ![[#]], !DIExpression()
35+
36+
target triple = "x86_64-unknown-linux-gnu"
37+
38+
@b = dso_local local_unnamed_addr global i32 0, align 4
39+
40+
define dso_local i32 @main() local_unnamed_addr #0 !dbg !10 {
41+
entry:
42+
%c = alloca [1 x i32], align 4, !DIAssignID !19
43+
call void @llvm.dbg.assign(metadata i1 undef, metadata !15, metadata !DIExpression(), metadata !19, metadata ptr %c, metadata !DIExpression()), !dbg !20
44+
%0 = load i32, ptr @b, align 4
45+
%tobool.not = icmp eq i32 %0, 0
46+
br i1 %tobool.not, label %while.end, label %while.body.lr.ph
47+
48+
while.body.lr.ph: ; preds = %entry
49+
%arrayidx1 = getelementptr inbounds [1 x i32], ptr %c, i64 0, i64 -1
50+
store i32 0, ptr %arrayidx1, align 4
51+
br label %while.body
52+
53+
while.body: ; preds = %while.body, %while.body.lr.ph
54+
call void @llvm.dbg.assign(metadata i32 0, metadata !15, metadata !DIExpression(), metadata !28, metadata ptr %c, metadata !DIExpression()), !dbg !20
55+
br label %while.body
56+
57+
while.end: ; preds = %entry
58+
call void @a(ptr noundef nonnull %c)
59+
ret i32 0
60+
}
61+
62+
declare !dbg !31 void @a(ptr noundef) local_unnamed_addr #2
63+
declare void @llvm.dbg.assign(metadata, metadata, metadata, metadata, metadata, metadata) #3
64+
65+
!llvm.dbg.cu = !{!0}
66+
!llvm.module.flags = !{!2, !3, !8}
67+
!llvm.ident = !{!9}
68+
69+
!0 = distinct !DICompileUnit(language: DW_LANG_C11, file: !1, producer: "clang version 17.0.0)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None)
70+
!1 = !DIFile(filename: "test.c", directory: "/")
71+
!2 = !{i32 7, !"Dwarf Version", i32 5}
72+
!3 = !{i32 2, !"Debug Info Version", i32 3}
73+
!8 = !{i32 7, !"debug-info-assignment-tracking", i1 true}
74+
!9 = !{!"clang version 17.0.0"}
75+
!10 = distinct !DISubprogram(name: "main", scope: !1, file: !1, line: 4, type: !11, scopeLine: 4, flags: DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !14)
76+
!11 = !DISubroutineType(types: !12)
77+
!12 = !{!13}
78+
!13 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
79+
!14 = !{!15}
80+
!15 = !DILocalVariable(name: "c", scope: !10, file: !1, line: 5, type: !16)
81+
!16 = !DICompositeType(tag: DW_TAG_array_type, baseType: !13, size: 32, elements: !17)
82+
!17 = !{!18}
83+
!18 = !DISubrange(count: 1)
84+
!19 = distinct !DIAssignID()
85+
!20 = !DILocation(line: 0, scope: !10)
86+
!28 = distinct !DIAssignID()
87+
!31 = !DISubprogram(name: "a", scope: !1, file: !1, line: 1, type: !32, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized, retainedNodes: !35)
88+
!32 = !DISubroutineType(types: !33)
89+
!33 = !{null, !34}
90+
!34 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !13, size: 64)
91+
!35 = !{}

0 commit comments

Comments
 (0)