Skip to content
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

Improve debuggability of IEnummerable<T> MoveNext methods #660

Open
jkotas opened this issue Feb 8, 2021 · 6 comments
Open

Improve debuggability of IEnummerable<T> MoveNext methods #660

jkotas opened this issue Feb 8, 2021 · 6 comments
Labels
area-NativeAOT-coreclr .NET runtime optimized for ahead of time compilation

Comments

@jkotas
Copy link
Member

jkotas commented Feb 8, 2021

Improve debugging experience for IEnummerable MoveNext method (when yield is used in a method). Switching to .frame N and then dumping local variables via dv /t /v results in no local variables and __this being unavailable.

@jkotas jkotas added the area-NativeAOT-coreclr .NET runtime optimized for ahead of time compilation label Feb 8, 2021
@MichalStrehovsky
Copy link
Member

__this is available, but it leaves much to be desired:

image

@MichalStrehovsky
Copy link
Member

Hm, the cordebuginfo.h protocol doesn't currently allow specifying that a local is placed behind an indirection. Wondering whether COFF/DWARF allow that in the first place.

Wondering if the easiest thing we could do is to

  • use the PDB information to get the mapping of locals and their ranges and
  • rewrite the IL of MoveNext to add a "ref X" local that gets initialized to point to the field in the state machine

Maybe do all of this only if we're building debug. RyuJIT is likely to optimize the locals away anyway.

@jkotas
Copy link
Member Author

jkotas commented Feb 9, 2021

I expect that people typically need to debug optimized retail binaries with NativeAOT. I do not think it is worth it to spend time on solutions that only work when building debug.

@MichalStrehovsky
Copy link
Member

Maybe using the same kind of debug records that C++ uses for lambda captures would work:

#include <vector>
#include <iostream>
#include <algorithm>
#include <functional>

int main()
{
    std::vector<int> c = { 42, 1, 8 };
    int fhtagn = 5;
    int phnglui = 8;
    c.erase(std::remove_if(c.begin(), c.end(),
        [fhtagn, phnglui](int n) {
        return n < (fhtagn + phnglui);
    }), c.end());
}

The captured locals are hoisted into a class but the debugger shows them as normal locals. This looks like the thing we need. I've reached out the the C++ team to help me find the CodeView incantation to do it. Then we'll need the relevant Dwarf incantation too.

@MichalStrehovsky
Copy link
Member

#735 fixes a lot of the experience. The variable still don't show up as proper locals, so keeping open for now.

@MichalStrehovsky
Copy link
Member

Rust change that makes locals appear properly: rust-lang/rust#83941

If I understand it right, it creates additional variables and points them to the fields on the capture.

The comments do have pointers on how to do this properly in DWARF ([DW_OP_deref, DW_OP_plus_uconst, offset, DW_OP_deref]).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-NativeAOT-coreclr .NET runtime optimized for ahead of time compilation
Projects
None yet
Development

No branches or pull requests

2 participants