[Lldb-commits] [lldb] [lldb] Implement basic support for reverse-continue (PR #112079)
via lldb-commits
lldb-commits at lists.llvm.org
Mon Nov 11 15:19:43 PST 2024
jimingham wrote:
> > My notion was that when you push a plan that has an intention to run in a direction, if the plan above it on the stack was going in the opposite direction, it has to be popped.
>
> That's in the current code in this PR but I agree that was the wrong direction. My experimental [reverse-continue-thread-plan](https://github.com/rocallahan/llvm-project/tree/reverse-continue-thread-plan) branch doesn't do this.
>
> > After all, you might be doing a backwards direction next, but hit a breakpoint while doing that. You then want to step FORWARDS from that breakpoint to check something out.
>
> Right.
>
> > Then if stepping backwards and forwards were working like lldb stepping currently works, you'd expect "continue" to return control to the backwards next to finish out the operation.
>
> There's a UX issue here: in the scenario you describe (hit breakpoint during reverse-next, step forward, continue) _should_ the reverse-step be resumed? Personally I think not. I think it's very confusing if "continue" ever causes reverse execution (and likewise if "reverse-continue" ever causes forward execution). So in this case I would say "reverse-continue" should resume the reverse-next but "continue" should pop it.
I have to play around with a working version more to know. I worry that people in a situation like this where there's a pending task people will lose important state because they forgot that "continue" doesn't mean "continue what I was doing" - which is what it currently means in lldb - but instead means "continue what I was doing if it happens to be going forwards". Not sure how to weigh the surprise of that vrs. the surprise of "continue" continuing backwards.
>
> This is helpful discussion but it doesn't directly address my question in [#112079 (comment)](https://github.com/llvm/llvm-project/pull/112079#issuecomment-2468857787). Can we focus on that?
So first off, I think ultimately I'm arguing against requiring: "we either have all forward or all backwards plans on any given thread plan stack" because I don't think that is flexible enough to support all the use cases we want to support.
But I thought I was giving a suggestion for your previous problem. IIUC, when you go to push a plan onto the plan stack you want to say "if this is a forward going plan, remove all the backwards going plans from the stack when you push it" and ditto for adding backwards going plans.
I was suggesting separating the actual direction a plan says the thread should go when it resumes from whether it is a "forward or backwards going plan" for the purposes of thread plan stack management. Then I was suggesting adding to the latter determinant the ability to say a plan doesn't have an opinion about the current forwards or backwards state of the current thread plan stack.
So for instance, if you are reverse continuing, and stop at a breakpoint with a condition, the ThreadPlanCallFunction that you push would have "no opinion" about the overall forwards or backwards state of the current plan stack. So it wouldn't require either forward or backwards going plans to be removed from the stack.
For this to work, we would have to require that all "no opinion" plans run only their thread. For condition expressions that should be good enough for most uses, and I don't know what it would mean to run the other threads anyway.
So in your specific case, you would stop at the breakpoint, and push the "no opinion" ThreadPlanCallFunction to handle the condition. When we check whether we need to pop the reverse continue plan from the stack on pushing this new function call plan, we would say "ah, that plan has no opinion, so we can just push it on the stack."
Then when we go to resume, we see that there's a "run me only" thread plan among the threads, and like we always do we run that one first (if there's more than one we run them all round robin till all the run me plans are done). But when we go to restart that thread we ask for the "actual" not the "nominal" direction, which for the call function thread plan is "forward".
Then when that call function thread plan is done, we pop it off the stack and check the result to see if the condition failed or succeeded. If it fails then you can just resume going whatever direction the youngest plan on the stack says to, without changing the plan stacks at all. But if it says stop, then we pass control to the next up plan on the stack to figure out what to do with the stop. You might be doing a fancy reverse continue plan that is doing something like "when I hit this breakpoint and pass this condition, do two more `next`-s and then stop".
Am I missing something?
https://github.com/llvm/llvm-project/pull/112079
More information about the lldb-commits
mailing list