-
Notifications
You must be signed in to change notification settings - Fork 10.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
clang produces confusing debug location for end of loops #91285
Comments
@llvm/issue-subscribers-debuginfo Author: Mārtiņš Možeiko (mmozeiko)
For simple loops like this:
```
int x = 0;
while (x == 0)
{
x = 1;
} // <-- end of loop
```
clang emits branch at end of loop to jump back to loop condition.
Debug information for this branch encodes location of beginning of loop - while location.
Here's the complete program: https://godbolt.org/z/E7x4b5Whb As you can see This leads to poor debugging experience. For example, if you put breakpoint on line 4 and try to step (F10) in VisualStudio debugger, then you will need to press F10 two times to get out of while loop. Because first time it hits breakpoint of "jmp" instruction at end of loop. Or in other words - if you put breakpoint on line 4 and run this program with F5, then it will hit line 4 breakpoint 3 times, when it should do that only 2 times. cl.exe compiles correct location, line 7, for "jmp" instruction at end of loop. I think branch emitted for end of loop (in this case WhileStmt, but for other type of loops too) should encode end of loop location, not beginning of loop: llvm-project/clang/lib/CodeGen/CGStmt.cpp Line 1066 in 6e5ed35
Here's a screenshot of clang compiled exe when I put breakpoint on line 4. You can see how it automatically puts second breakpoint on Here's a screenshot of cl.exe compiled code, showing only one breakpoint on line 4, and proper line 7 location for |
@llvm/issue-subscribers-clang-codegen Author: Mārtiņš Možeiko (mmozeiko)
For simple loops like this:
```
int x = 0;
while (x == 0)
{
x = 1;
} // <-- end of loop
```
clang emits branch at end of loop to jump back to loop condition.
Debug information for this branch encodes location of beginning of loop - while location.
Here's the complete program: https://godbolt.org/z/E7x4b5Whb As you can see This leads to poor debugging experience. For example, if you put breakpoint on line 4 and try to step (F10) in VisualStudio debugger, then you will need to press F10 two times to get out of while loop. Because first time it hits breakpoint of "jmp" instruction at end of loop. Or in other words - if you put breakpoint on line 4 and run this program with F5, then it will hit line 4 breakpoint 3 times, when it should do that only 2 times. cl.exe compiles correct location, line 7, for "jmp" instruction at end of loop. I think branch emitted for end of loop (in this case WhileStmt, but for other type of loops too) should encode end of loop location, not beginning of loop: llvm-project/clang/lib/CodeGen/CGStmt.cpp Line 1066 in 6e5ed35
Here's a screenshot of clang compiled exe when I put breakpoint on line 4. You can see how it automatically puts second breakpoint on Here's a screenshot of cl.exe compiled code, showing only one breakpoint on line 4, and proper line 7 location for |
Hi, thanks for filing this issue. Breakpoint locations on braces seems to a perennial question (though maybe that is just in relation to functions) but I can't recall the discussions or answers off the top of my head. I think @pogo59 or @dwblaikie may have an opinion on whether this is desirable or not. A quick observation -
I was wondering about what happens if you remove the loop's braces (line 7 is the closing brace). It looks like in that case MSVC (v19.latest on godbolt) attributes the |
In code without braces I feel like this behavior is fine - attributing jmp to line 5 does not cause any harm. If user puts breakpoint on line 5, they get exactly one breakpoint. No special "ghost" breakpoints like in my initial example appear. You will break exactly once on this line. I feel that's exactly what you would want in unoptimized code - it should be as intuitive as possible. In optimized code - fine I understand that lines are rearranged and sometimes code will happen to produce multiple breakpoints. I would not be very surprised about that. But all of what I'm talking is about "debug" builds. |
Associating the closing |
Be careful not to use the end of the scope, assuming it's the closing brace. If the block lacks braces then the end of the scope will be inside the body, and stepping there might be confusing in some cases (see the related bugs I linked above) |
For simple loops like this:
clang emits branch at end of loop to jump back to loop condition.
Debug information for this branch encodes location of beginning of loop - while location.
This is with v18.1.5, but happens with earlier versions too (v17 and v16). No optimizations are enabled.
Here's the complete program: https://godbolt.org/z/E7x4b5Whb
As you can see
br label %while.cond, !dbg !18, !llvm.loop !23
enodes same!dbg !18
as other instructions, which means line 4, not line 7. The AST encodesWhileStmt
location as<line:4:5, line:7:5>
- so clearly it has information about end of loop at line 7.This leads to poor debugging experience.
For example, if you put breakpoint on line 4 and try to step (F10) in VisualStudio debugger, then you will need to press F10 two times to get out of while loop. Because first time it hits breakpoint of "jmp" instruction at end of loop.
Or in other words - if you put breakpoint on line 4 and run this program with F5, then it will hit line 4 breakpoint 3 times, when it should do that only 2 times.
cl.exe compiles correct location, line 7, for "jmp" instruction at end of loop.
I think branch emitted for end of loop (in this case WhileStmt, but for other type of loops too) should encode end of loop location, not beginning of loop:
llvm-project/clang/lib/CodeGen/CGStmt.cpp
Line 1066 in 6e5ed35
Here's a screenshot of clang compiled exe when I put breakpoint on line 4. You can see how it automatically puts second breakpoint on
jmp
, and also mixed source-disassembly window showswhile (x == 0)
forjmp
instruction.Here's a screenshot of cl.exe compiled code, showing only one breakpoint on line 4, and proper line 7 location for
jmp
instruction.The text was updated successfully, but these errors were encountered: