MimIR
MimIR is my Intermediate Representation
Loading...
Searching...
No Matches
conv.h
Go to the documentation of this file.
1#pragma once
2
3#include <mim/def.h>
4#include <mim/phase.h>
5
6namespace mim::plug::cps {
7
8/// Full CPS conversion in one recursive rewrite.
9///
10/// Each term-level, direct-style function
11/// ```
12/// f: [a: A] → B
13/// ```
14/// becomes
15/// ```
16/// f_cps: Cn [a: A, Cn B]
17/// ```
18/// and every use of `f` is replaced by `%cps.cps2ds_dep (A, λ a: B) f_cps` to remain type-correct.
19///
20/// Call sites are lifted on the fly:
21/// When the recursive rewrite encounters `App (%cps.cps2ds_dep (T, U) k) arg` inside a continuation,
22/// it allocates a fresh continuation `cont` receiving the result, records the pending call `k (arg, cont)`,
23/// and uses `cont`'s variable as the value of the App.
24/// Once the enclosing Lam is done, the pending calls are wired up in encounter order - which respects
25/// data dependencies, because operands are always rewritten before their users:
26/// ```
27/// lam = k₀ (arg₀, cont₀)
28/// cont₀ = k₁ (arg₁, cont₁)
29/// ...
30/// contₙ = rewritten body of lam
31/// ```
32/// A lifted call simply lives in the Lam whose body rewriting first reaches it.
33/// Rewrites whose result mentions such a continuation variable are scoped to that Lam (see Conv::map) and
34/// re-derived - and thus re-lifted - in sibling scopes.
35class Conv : public RWPhase {
36public:
39
40private:
41 /// A lifted call `callee (arg, cont)` waiting to be wired into the body of the enclosing Lam.
42 struct Pending {
43 const Def* callee; ///< CPS callee `k: Cn [T, Cn U]`.
44 const Def* arg; ///< Rewritten argument - still without the continuation.
45 Lam* cont; ///< Fresh continuation receiving the result of the call.
46 };
47
48 /// RAII guard for rewriting the body of one mutable Lam:
49 /// fences pending_, pushes a map scope for contaminated rewrites, and tracks whether lifting is legal here.
50 class Scope {
51 public:
52 Scope(Conv& conv, bool liftable)
53 : conv_(conv)
54 , base_(conv.pending_.size())
55 , old_liftable_(conv.liftable_) {
56 conv_.push();
57 conv_.liftable_ = liftable;
58 }
59 ~Scope() {
60 assert(conv_.pending_.size() == base_ && "pending calls must have been wire()d");
61 conv_.pop();
62 conv_.liftable_ = old_liftable_;
63 }
64
65 size_t base() const { return base_; }
66
67 private:
68 Conv& conv_;
69 size_t base_;
70 bool old_liftable_;
71 };
72
73 const Def* rewrite_mut_Lam(Lam*) final;
74 const Def* rewrite_imm_App(const App*) final;
75
76 /// Routes rewrites that mention scoped (continuation/binder) variables into the current Lam's map scope;
77 /// everything else goes into the root map and is shared globally.
78 using Rewriter::map;
79 const Def* map(const Def*, const Def*) final;
80
81 /// Converts direct-style `f: [a: A] → B` to `f_cps: Cn [a: A, Cn B]` and returns the `cps2ds_dep`-wrapped f_cps.
82 const Def* convert(Lam*);
83 /// Turns the call `k (arg, cont)` into a Pending entry and returns `cont`'s variable as call result.
84 const Def* lift(const Def* k, const Def* arg, const App* old_app);
85 /// Wires all Pending calls above @p base around @p body and returns the new body.
86 const Def* wire(size_t base, const Def* body);
87
88 Vector<Pending> pending_;
89 Vars scoped_;
90 bool liftable_ = false;
91};
92
93} // namespace mim::plug::cps
Base class for all Defs.
Definition def.h:261
A function.
Definition lam.h:110
flags_t annex() const
Definition phase.h:81
RWPhase(World &world, std::string name, Analysis *analysis=nullptr)
Definition phase.h:316
World & world()=delete
Hides both and forbids direct access.
virtual void push()
Definition rewrite.h:38
virtual const Def * map(const Def *old_def, const Def *new_def)
Definition rewrite.h:45
virtual void pop()
Definition rewrite.h:39
The World represents the whole program and manages creation of MimIR nodes (Defs).
Definition world.h:36
const Def * rewrite_mut_Lam(Lam *) final
Definition conv.cpp:20
Conv(World &world, flags_t annex)
Definition conv.h:37
const Def * rewrite_imm_App(const App *) final
Definition conv.cpp:70
const Def * map(const Def *, const Def *) final
Definition conv.cpp:15
The CPS Plugin
Definition cps.h:8
u64 flags_t
Definition types.h:39
Sets< const Var >::Set Vars
Definition def.h:99
@ Lam
Definition def.h:109
@ App
Definition def.h:109