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

Add a Control construct and re-engineer closure conversion #138

Draft
wants to merge 201 commits into
base: development
Choose a base branch
from

Conversation

Hugobros3
Copy link
Contributor

@Hugobros3 Hugobros3 commented Jul 3, 2023

This 🚧 draft 🚧 PR adds a control construct as found in Shady and performs a significant amount of refactoring on the IR to support closure conversion more robustly. This is not currently merge-able and exists as a tracking issue.

Current changelist:

  • Add control intrinsic and matching JoinPointType
  • Add an explicit ReturnType type that encodes the codomain of a function.
    • Use that as the ground-truth for whether a function is returning or not, in place of the order
  • Refactored a bunch of passes to use a unified Rewriter
  • Improve scoping analysis to produce a nesting
    • Made the scheduler::early use the new scoping analysis
    • Add a new World::scoped_dump that uses the new scope analysis to pretty-print IR
    • Add a graphviz IR dumping utility, that can also dump the world with scoping
  • Add a lift2cff pass
  • Rewrite closure conversion entirely and make it robust

The lowering for this is tricky: setjmp/longjmp cannot be safely used inside functions because they can overwrite side effects that have happened in-between the control call and consuming the token. One solution is to emit cps-style code instead of direct-style, and then we can use tailcalls and perform manual stack pointer adjustments instead.

However there are backends where this will not be permissible (those who lack true function calls mostly) and we will need to find an alternative solution for those.

Still TODO:

  • 🚧 Per-backend passes (in a way that doesn't break the kernels analysis)
  • Lower control to something sensible in non-shady backends
  • Aggressively eliminate closures for call-challenged backends

Hugobros3 and others added 30 commits January 18, 2023 10:57
This reverts commit 9eaba5d.
This reverts commit 72d2dee.
This reverts commit a9ad152.
This reverts commit dc54cca.
This reverts commit 2c0ce6c.
Hugobros3 and others added 30 commits July 25, 2023 16:11
Many methods in the LLVM back-end assume a continuation as one of the operands of calls to intrinsics. This is inflexible and brittle - this commit instead have the intrinsics yield LLVM values directly (see `emit_intrinsic`), and then `emit_epilogue` is made responsible for forwarding those values alongside control-flow.

To help in this, we extract a new `emit_call` method: this method is in charge of "making calls", with supplied LLVM values. What is being called can vary: it can be a basic block, a direct-style function, a return parameter, a closure etc ...

`emit_epilogue` works in concert with `emit_call` and is in charge of calling it a second time for direct-style calls, for forwarding the argumnents.

Finally, `emit_epilogue` might need to terminate the basic block if it otherwise ends in a function call.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants