diff --git a/llvm/lib/IR/DebugInfoMetadata.cpp b/llvm/lib/IR/DebugInfoMetadata.cpp --- a/llvm/lib/IR/DebugInfoMetadata.cpp +++ b/llvm/lib/IR/DebugInfoMetadata.cpp @@ -1387,7 +1387,10 @@ Ops.push_back(Offset); } else if (Offset < 0) { Ops.push_back(dwarf::DW_OP_constu); - Ops.push_back(-Offset); + // Avoid UB when encountering LLONG_MIN, because in 2's complement + // abs(LLONG_MIN) is LLONG_MAX+1. + uint64_t AbsMinusOne = -(Offset+1); + Ops.push_back(AbsMinusOne + 1); Ops.push_back(dwarf::DW_OP_minus); } } diff --git a/llvm/test/DebugInfo/salvage-overflow.ll b/llvm/test/DebugInfo/salvage-overflow.ll new file mode 100644 --- /dev/null +++ b/llvm/test/DebugInfo/salvage-overflow.ll @@ -0,0 +1,45 @@ +; RUN: opt %s -sroa -early-cse -S | FileCheck %s +; CHECK: DIExpression(DW_OP_constu, 9223372036854775808, DW_OP_minus, DW_OP_stack_value) +; Created from the following C input (and then delta-reduced the IR): +; +; extern unsigned long long use(unsigned long long); +; void f(unsigned long long x) { +; for (; x > 0; x --) { +; unsigned long long y = x + 0x8000000000000000; +; use(x); +; } +; } + +define void @f(i64 noundef %x) #0 !dbg !9 { +entry: + %x.addr = alloca i64, align 8 + %y = alloca i64, align 8 + br label %for.cond +for.cond: ; preds = %for.inc, %entry + %0 = load i64, i64* %x.addr, align 8 + %1 = bitcast i64* %y to i8* + call void @llvm.dbg.declare(metadata i64* %y, metadata !15, metadata !DIExpression()) +, !dbg !29 + %2 = load i64, i64* %x.addr, align 8 + %add = add i64 %2, -9223372036854775808 + store i64 %add, i64* %y, align 8 + br label %for.cond +} +declare void @llvm.dbg.declare(metadata, metadata, metadata) #1 + +!llvm.module.flags = !{!3,!7} + +!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None, sysroot: "/") +!1 = !DIFile(filename: "t.c", directory: "/") +!3 = !{i32 2, !"Debug Info Version", i32 3} +!7 = !{i32 7, !"frame-pointer", i32 2} +!9 = distinct !DISubprogram(name: "f", scope: !1, file: !1, line: 2, type: !10, scopeLine: 2, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !13) +!10 = !DISubroutineType(types: !11) +!11 = !{null, !12} +!12 = !DIBasicType(name: "unsigned long long", size: 64, encoding: DW_ATE_unsigned) +!13 = !{} +!15 = !DILocalVariable(name: "y", scope: !16, file: !1, line: 4, type: !12) +!16 = distinct !DILexicalBlock(scope: !17, file: !1, line: 3, column: 23) +!17 = distinct !DILexicalBlock(scope: !18, file: !1, line: 3, column: 3) +!18 = distinct !DILexicalBlock(scope: !9, file: !1, line: 3, column: 3) +!29 = !DILocation(line: 4, column: 24, scope: !16)