[eudsl-llvmpy] MIR: run codegen to a named pass and retain the MIR for inspection (e.g. post-RA)
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 79
- Forks
- 14
- Avg merge
- 11h 43m
- Merged PRs (30d)
- 72
Description
Follow-up to #648. Today MirModule.emit_object(scheduler=, regalloc=) runs the entire back half of codegen (-start-after=finalize-isel through object emission) and returns the object bytes. There is no way to run codegen up to a chosen pass and get the intermediate MachineFunctions back for inspection — so you can't, from Python, observe the MIR after a specific stage (e.g. after register allocation / virtregrewriter, where the function is no longer in SSA form and has no virtual registers), which is exactly what you want when debugging a custom RegAllocBase/MachineSchedStrategy.
Proposal
Add a "run to a named pass and retain the MIR" entry point, e.g.:
mmi2 = mmi.run_to("virtregrewriter", regalloc="my-alloc") # or stop_before=
print(mmi2.to_mir()) # inspect post-RA, non-SSA MIR
Semantics: run the codegen pipeline from finalize-isel up to (and including / before) the named pass, then retain the resulting MachineFunctions in the returned MirModule for inspection via the existing to_mir() / machine_function() surface — rather than continuing to emission and freeing them.
Mechanism (mirrors what already exists)
- LLVM already provides process-global
-stop-after=<pass>/-stop-before=<pass>cl::opts, analogous to the-start-after=finalize-iselthatemit_objectalready sets and restores (see theRestoreRAII inMirModule::emitObject,src/MIR/Machine.cpp). Set/restorestop-after/stop-beforethe same way (GIL-serialized; no lock). - Retaining MIR after stopping is the same trick
create_machine_functionuses for the ISel boundary: don't append the object-emission passes (addPassesToEmitFilewould addFreeMachineFunctionPassand free the functions), keep theMachineModuleInfoWrapperPassalive in the returned wrapper's owned state (theBuildOwned/EmittedOwnedvariant inMachine.cpp), so theMachineFunctions stay queryable — exactly like the current build/inspect path. - The scheduler/regalloc selection (
-misched,RegisterRegAlloc::setDefault) and thependingCodegenErrorstash/re-raise machinery should compose unchanged, so you can run a custom allocator and stop right after it.
Scope
- New
MirModule.run_to(pass_name, *, stop_before=False, scheduler=None, regalloc=None)(name TBD) that runsfinalize-isel -> <pass>and returns aMirModulewhoseMachineFunctions are retained. - Validate the pass name against the registered pass pipeline; an unknown name raises a catchable Python error (as
emit_objectdoes for unknown scheduler/regalloc names). - Reuse the existing state machine so a module can be inspected and then still
emit_object'd (or make the retain-vs-emit interaction explicit and one-shot, matching the currentBuildOwned/EmittedOwnedhandling). - Tests: run to
virtregrewriterwith a custom allocator, assert the returned MIR has no virtual registers / uses physregs (i.e. is post-RA, non-SSA); run to a pre-RA pass and assert vregs are still present; unknown-pass-name raises. Keep the 100% C++ coverage gate.
Notes
- This pairs naturally with the existing
to_mir()and the-start-after=finalize-iselplumbing; it's mostly option set/restore + retaining the MMI wrapper, not new pipeline construction. - Useful well beyond regalloc (inspecting scheduling results, prologue/epilogue insertion, etc.).
cc #600
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in src/MIR/Machine.cpp by tracing MirModule::emitObject, its Restore handling for codegen options, and the BuildOwned/EmittedOwned state used by create_machine_function. Compare how the existing to_mir() and machine_function() surfaces retain MachineFunction data. Done means a named-pass run preserves inspectable MIR, handles pre- and post-RA cases, rejects unknown passes, and keeps the existing coverage gate passing.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp, python
- Domain
- backend-api-design, compilers
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 38/100