oxinabox / MagneticReadHead.jl

A cassette-based debugger | The Other Debugger
MIT License
50 stars 6 forks source link

IR Pass based #14

Closed oxinabox closed 5 years ago

oxinabox commented 5 years ago

To be a Real debugger, you need to be able to step though a method, call by call, seeing how all the local variables are changing.

Not just our current game of Leap to the next call and examine it's inputs. (and with #5 outputs)

This PR is to be able to do that, or at least the core parts of that

jrevels commented 5 years ago

So cool :)

jrevels commented 5 years ago

This is actually kind of interesting. @vtjnash + @Keno + me + others have been musing for a while about what it would look like for pre-type-inference IR to be fully SSA form (like the optimizer's IR). If that were to happen, you couldn't accomplish the thing you've implemented here via a simple Cassette pass. Though I guess we could bake-in additional mechanisms to ensure this kind of thing could still work (e.g. the compiler could keep around a separate queryable cache for the original variable names etc.). This change isn't likely to happen in the near future (or maybe ever) anyway, just food for thought.

vtjnash commented 5 years ago

FWIW, I don't think we should ever delete the ability to handle Slots from inference. While SSA form is helpful for writing mutation passes (it simplifies updating non-local information), it's not always a clear win (there's a reason that clang avoids them). So don't avoid them just because the later optimizer passes don't need to optimize them, or think that means we need to remove them from the IR.

jrevels commented 5 years ago

FWIW, I don't think we should ever delete the ability to handle Slots from inference. While SSA form is helpful for writing mutation passes (it simplifies updating non-local information), it's not always a clear win (there's a reason that clang avoids them). So don't avoid them just because the later optimizer passes don't need to optimize them, or think that means we need to remove them from the IR.

Certainly, not advocating for removing slots. Just pointing out that this PR demonstrates one of the potential negative consequences of removing them (it'd make this PR harder to implement) 🙂

oxinabox commented 5 years ago

With a bit more tinkering it works!

julia-1.1 --project=. test/test_assignment_capture.jl
Dict{Any,Any} with 3 entries:
  Symbol("##eg_last#381") => Dict{Any,Any}()
  :z => 6
  Symbol("##eg2#379") => Dict{Any,Any}(:y=>5,Symbol("##+#378")=>Dict{Any,Any}(),Symbol("##eg21#372")=>Dict{Any,Any}(Symbol("##*#371")=>Dict{Any,Any}()),Symbol("##eg3#377")=>Dict{Any,Any}(Symbol("##+#376")=>Dict{Any,Any}()),:ret=>6)

@jrevels do you think this might be a nice example for the Cassette docs? It is a lot shorter and I think might be simpler than the sliceprintln thing

oxinabox commented 5 years ago

All the tests are probably broken now. But this now has the core functionality (and even User Commands working) around being able to break/step midway through a method. This is done by inserting an extra call in between every statement.

Todo is to hook the breakpoint stuff in (right now it just initially begins by breakpointing immediately), then to add some polish by not recompiling literally everything and adding in this code. This can be done by not recurseing calls that we are going to StepNext over; though the problem there is what if it called a breakpointed method. So probably actually need to be a bit smarter than that, but that is the principle.

oxinabox commented 5 years ago

Merged into #23