llvm / llvm/llvm-project

[SelectionDAG] Variable location dropped if dbg_declare and its operand instr are in different blocks

Open
#184,430 1 comment 0 reactions 0 assignees View on GitHub
debuginfo llvm:SelectionDAG
Dominant language
LLVM
Stars
40.5k
Forks
18.7k
PR merge metrics
PR metrics pending

Description

Reproducer
```c
int main(void)
{
// This kills the debug-info for unsafe variables
do { } while (0);
int unsafe_var = 123;
unsigned long long ptr = (unsigned long long)&unsafe_var;
return 0;
}
```

Compilation Flags
```
-g -fsanitize=safe-stack
```

Godbolt: https://godbolt.org/z/4dMsE9qh9

Notice `unsafe_var`, a variable on the unsafe-stack with `-fsanitize=safe-stack` active, loses debug-info in versions of Clang >= 11.

This issue started with Clang / LLVM 11.0.0 bisected from this commit: https://github.com/llvm/llvm-project/commit/8e77b33b3c67aa8f2580671b019eeb3862651ecb.

With trunk
```
> clang --version
clang version 23.0.0git
(built from main @ abbba22f45665b25b01693fc7a41712660b3c124)
> clang -g -fsanitize=safe-stack -O0 -mllvm -debug-only=isel -S safestack.c -o /dev/null
```

We get
```
...
Total amount of phi nodes to update: 0
Total amount of phi nodes to update: 0
FastISel missed
SelectionDAG visiting dbg_declare: #dbg_declare(ptr %unsafe_stack_ptr, !22, !DIExpression(DW_OP_constu, 4, DW_OP_minus), !23)
dbg_declare: Dropping debug info (could not emit func-arg dbg_value)
...
```

This indicates the drop of debug info.

This stems from SelectionDAGBuilder here: https://github.com/llvm/llvm-project/blob/62cfe1659edff8874f2d814ee356cfc9199f62d5/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp#L1275-L1279

So `NodeMap[Address]` does not exist where, during a debug session, `Address->dump()` equates to:
```
%unsafe_stack_ptr = load ptr, ptr @__safestack_unsafe_stack_ptr, align 8, !dbg !19
```

The above is located in the `entry` Basic Block in the LLVM IR, however, the `dbg_declare` at the time of `handleDebugDeclare` is under `do.end`:
```
do.end: ; preds = %do.body
#dbg_declare(ptr %unsafe_stack_ptr, !23, !DIExpression(DW_OP_constu, 4, DW_OP_minus), !24)
```

It is my understanding that `NodeMap` is scoped to each basic block, so it makes sense it's not found when processing `do.end`.

The entire LLVM IR at the point of the error `dbg_declare: Dropping debug info (could not emit func-arg dbg_value)` is:
```
; Function Attrs: noinline nounwind optnone safestack uwtable
define dso_local i32 @main() #0 !dbg !12 !annotation !18 {
entry:
%unsafe_stack_ptr = load ptr, ptr @__safestack_unsafe_stack_ptr, align 8, !dbg !19
%unsafe_stack_static_top = getelementptr i8, ptr %unsafe_stack_ptr, i32 -16
store ptr %unsafe_stack_static_top, ptr @__safestack_unsafe_stack_ptr, align 8
%retval = alloca i32, align 4
%ptr = alloca i64, align 8
store i32 0, ptr %retval, align 4
br label %do.body, !dbg !20

do.body: ; preds = %entry
br label %do.end, !dbg !21

do.end: ; preds = %do.body
#dbg_declare(ptr %unsafe_stack_ptr, !23, !DIExpression(DW_OP_constu, 4, DW_OP_minus), !24)
%0 = getelementptr i8, ptr %unsafe_stack_ptr, i32 -4, !dbg !24
store i32 123, ptr %0, align 4, !dbg !24
#dbg_declare(ptr %ptr, !25, !DIExpression(), !26)
%1 = getelementptr i8, ptr %unsafe_stack_ptr, i32 -4, !dbg !27
%2 = ptrtoint ptr %1 to i64, !dbg !27
store i64 %2, ptr %ptr, align 8, !dbg !26
store ptr %unsafe_stack_ptr, ptr @__safestack_unsafe_stack_ptr, align 8, !dbg !28
ret i32 0, !dbg !28
}
```

Contributor guide

Open the contributing guide

Research direction

Start in llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp around the cited handleDebugDeclare path, focusing on the block-scoped NodeMap lookup. Compile the supplied safestack.c reproducer with -g -fsanitize=safe-stack and inspect the debug output; done means unsafe_var retains debug information instead of being dropped when its declaration and operand are in different blocks.

Written by the indexing model from the issue text.

Assessment

Tech stack
c
Domain
compilers
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
38/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.