llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
27.81k stars 11.45k forks source link

[debuginfo] [optimizations] " opt -passes = 'default<O0>' " leads a non-null pointer to be a NULL pointer, according the relevant debug information. #88755

Open edumoot opened 4 months ago

edumoot commented 4 months ago

LLVM 18.1.2 (commit 261aae0c) LLVM 17.0.6 (commit, 6009fe18)

Reproduce with:

clang -g -O0 case.c -Xclang -disable-O0-optnone -emit-llvm -c -o case.bc
opt -passes='default<O0>' case.bc  -o case.opt.bc
llc --relocation-model=pic case.opt.bc -o case.s
clang case.s -o case.out

Results:

The value of pointer p_j is not correct. It should be pointing variable d, with the same value with p_f, instead of p_k.

(lldb) file case.out
Current executable set to '/home/ad/Downloads/lldb/reproduce_bugs/case.out' (x86_64).
(lldb) b case.c:16
Breakpoint 1: where = case.out`func_a + 57 at case.c:16:7, address = 0x00000000000011b9
(lldb) r
Process 2852140 launched: '/home/ad/Downloads/lldb/reproduce_bugs/case.out' (x86_64)
Process 2852140 stopped
* thread #1, name = 'case.out', stop reason = breakpoint 1.1
    frame #0: 0x00005555555551b9 case.out`func_a(p=5) at case.c:16:7
   13       int *p_i = &g1;
   14       int *p_j = &d;
   15       int *p_k = (void*)0;
-> 16       g2++;
   17       return g1;
   18   }
   19   
(lldb) fr v
(int) p = 5
(int *) p_a = 0x0000555555558030
(int *) p_b = 0x0000555555558030
(int *) p_c = 0x0000555555558030
(int) d = 1000
(int *) p_e = 0x0000000000000000
(int *) p_f = 0x00007fffffffdc4c
(int *) p_h = 0x0000555555558030
(int *) p_i = 0x0000555555558030
(int *) p_j = 0x0000000000000000
(int *) p_k = 0x0000000000000000

and GDB shows the similar results.

Breakpoint 2, func_a (p=5) at case.c:16
16      g2++;
(gdb) info locals
p_a = 0x555555558030 <g1>
p_b = 0x555555558030 <g1>
p_c = 0x555555558030 <g1>
d = 1000
p_e = 0x0
p_f = 0x7fffffffde8c
p_h = 0x555555558030 <g1>
p_i = 0x555555558030 <g1>
p_j = 0x0
p_k = 0x0

cat case.c

#include <stdio.h>
static unsigned g1 = 15;
static unsigned g2 = 15;
static int  func_a(int  p)
{ /* block id: 3 */
    int *p_a = &g1;
    int *p_b = &g1;
    int *p_c = &g1;
    int d = 1000;
    int *p_e = (void*)0;
    int *p_f = &d;
    int *p_h = &g1;
    int *p_i = &g1;
    int *p_j = &d;
    int *p_k = (void*)0;
    g2++;
    return g1;
}

int main (void)
{   int i = 5;
    printf("%d",func_a(i));
    return 0;
}
llvmbot commented 4 months ago

@llvm/issue-subscribers-debuginfo

Author: Yachao Zhu (edumoot)

LLVM 18.1.2 (commit [261aae0c](https://github.com/llvm/llvm-project/commit/26a1d6601d727a96f4301d0d8647b5a42760ae0c)) LLVM 17.0.6 (commit, [6009fe18](https://github.com/llvm/llvm-project/commit/6009708b4367171ccdbf4b5905cb6a803753fe18)) Reproduce with: ```compiling pipeline clang -g -O0 case.c -Xclang -disable-O0-optnone -emit-llvm -c -o case.bc opt -passes='default<O0>' case.bc -o case.opt.bc llc --relocation-model=pic case.opt.bc -o case.s clang case.s -o case.out ``` Results: The value of pointer p_j is not correct. It should be pointing variable d, with the same value with p_f, instead of p_k. ``` (lldb) file case.out Current executable set to '/home/ad/Downloads/lldb/reproduce_bugs/case.out' (x86_64). (lldb) b case.c:16 Breakpoint 1: where = case.out`func_a + 57 at case.c:16:7, address = 0x00000000000011b9 (lldb) r Process 2852140 launched: '/home/ad/Downloads/lldb/reproduce_bugs/case.out' (x86_64) Process 2852140 stopped * thread #1, name = 'case.out', stop reason = breakpoint 1.1 frame #0: 0x00005555555551b9 case.out`func_a(p=5) at case.c:16:7 13 int *p_i = &g1; 14 int *p_j = &d; 15 int *p_k = (void*)0; -> 16 g2++; 17 return g1; 18 } 19 (lldb) fr v (int) p = 5 (int *) p_a = 0x0000555555558030 (int *) p_b = 0x0000555555558030 (int *) p_c = 0x0000555555558030 (int) d = 1000 (int *) p_e = 0x0000000000000000 (int *) p_f = 0x00007fffffffdc4c (int *) p_h = 0x0000555555558030 (int *) p_i = 0x0000555555558030 (int *) p_j = 0x0000000000000000 (int *) p_k = 0x0000000000000000 ``` and GDB shows the similar results. ``` Breakpoint 2, func_a (p=5) at case.c:16 16 g2++; (gdb) info locals p_a = 0x555555558030 <g1> p_b = 0x555555558030 <g1> p_c = 0x555555558030 <g1> d = 1000 p_e = 0x0 p_f = 0x7fffffffde8c p_h = 0x555555558030 <g1> p_i = 0x555555558030 <g1> p_j = 0x0 p_k = 0x0 ``` `cat case.c` ``` #include <stdio.h> static unsigned g1 = 15; static unsigned g2 = 15; static int func_a(int p) { /* block id: 3 */ int *p_a = &g1; int *p_b = &g1; int *p_c = &g1; int d = 1000; int *p_e = (void*)0; int *p_f = &d; int *p_h = &g1; int *p_i = &g1; int *p_j = &d; int *p_k = (void*)0; g2++; return g1; } int main (void) { int i = 5; printf("%d",func_a(i)); return 0; } ```
edumoot commented 4 months ago

We will get the same debug information on the pointer variable, with level3 in "1, 2, 3" and level4 in "0, 1, 2, 3 ":

llc -O{level3}--relocation-model=pic case.opt.bc -o case.s
clang -O{level4}case.s -o case.out
jmorse commented 4 months ago

I've only looked at a shallow level, but I suspect the optimiser is completely eliminating the "d" variable as it's constant, leaving some of the pointer variables with nothing to point at. AFAIUI we would be able to support this scenario if LLVM were able to use the implicit pointer feature of DWARF, DW_OP_implicit_pointer. However, that's not currently in a state where it can be used, alas.

If I'm reading the variable information correctly, p_j is described as a null pointer at the line where the debuggers stop? That might be another defect as the variable is best described as "optimised out" on all lines.