MimIR
MimIR is my Intermediate Representation
Loading...
Searching...
No Matches
lower_typed_clos.h
Go to the documentation of this file.
1#pragma once
2
3#include <queue>
4
5#include <mim/phase.h>
6
7#include <mim/plug/mem/mem.h>
8
10
11namespace mim::plug::clos::phase {
12
13/// This pass lowers *typed closures* to *untyped closures*.
14/// For details on typed closures, see ClosConv.
15/// In general, untyped closure have the form `(pointer-to-environment, code)` with the following exceptions:
16/// * Lam%s in callee-position should be λ-lifted and thus don't receive an environment.
17/// * External and imported (not set) Lam%s also don't receive an environment.
18/// They are appropriately η-wrapped by ClosConv.
19/// * If the environment is of integer type, it's directly stored in the environment-pointer ("unboxed").
20/// @note In theory this should work for other primitive types as well, but the LL backend does not handle the
21/// required conversion correctly.
22///
23/// Further, first class continuations are rewritten to returning functions.
24/// They receive `⊥` as a dummy continuation.
25/// Therefore Clos2SJLJ should have taken place prior to this pass.
26///
27/// This pass will heap-allocate ClosKind::esc closures and stack-allocate everything else.
28/// These annotations are introduced by LowerTypedClosPrep.
29///
30/// The rewrite carries a *mem token* along each function body (LowerTypedClos::lvm_ / LowerTypedClos::lcm_) so
31/// that the `mem.alloc`/`mem.store` it inserts for boxed environments are threaded into the mem chain.
32/// This stateful, order-sensitive threading is why LowerTypedClos::rewrite intercepts whole classes of nodes
33/// instead of relying on the per-node hooks alone.
34/// A converted Lam's body is enqueued and rewritten later, seeded with that body's own initial mem token.
35class LowerTypedClos : public RWPhase {
36public:
37 using RWPhase::RWPhase;
38
39private:
40 /// A pending body rewrite: the initial mem tokens (old @c lvm, new @c lcm) plus the old and new Lam.
41 struct Todo {
42 const Def* lvm;
43 const Def* lcm;
44 Lam* old_lam;
45 Lam* new_lam;
46 };
47
48 void finalize() final;
49 const Def* rewrite(const Def* def) final;
50 const Def* rewrite_imm(const Def* def) final;
51 const Def* rewrite_imm_App(const App*) final;
52
53 /// Describes how the environment should be treated.
54 enum Mode {
55 Box = 0, ///< Environment is boxed (default).
56 Unbox, ///< Environment is of primitive type (currently `iN`s) and directly stored in the pointer.
57 No_Env ///< Lambda has no environment (lifted, top-level).
58 };
59
60 /// Create a new Lam stub.
61 /// @p adjust_bb_type is true if the @p lam should be rewritten to a returning function.
62 Lam* make_stub(Lam* lam, Mode mode, bool adjust_bb_type);
63
64 /// Pointer type used to represent environments.
65 const Def* env_type() { return new_world().call<mem::Ptr0>(new_world().sigma()); }
66
67 /// Dummy return continuation.
68 const Def* dummy_ret() { return new_world().bot(new_world().cn(new_world().call<mem::M>(0))); }
69
70 std::queue<Todo> worklist_;
71
72 /// @name memory-tokens
73 /// The mem token threaded through the body currently being rewritten.
74 ///@{
75 const Def* lvm_ = nullptr; ///< Last visited memory token.
76 const Def* lcm_ = nullptr; ///< Last created memory token.
77 ///@}
78};
79
80} // namespace mim::plug::clos::phase
Base class for all Defs.
Definition def.h:289
A function.
Definition lam.h:91
World & new_world()
Create new Defs into this.
Definition phase.h:379
RWPhase(World &world, std::string name, Analysis *analysis=nullptr)
Definition phase.h:334
const Def * call(const Def *callee, auto &&arg, Args &&... args)
Definition world.h:674
const Def * sigma(Defs ops)
Definition world.cpp:506
const Def * bot(const Def *type)
Definition world.h:604
This pass lowers typed closures to untyped closures.
const Def * rewrite(const Def *def) final
void finalize() final
Run after all roots have been walked but still before the two worlds are swapped.
RWPhase(World &world, std::string name, Analysis *analysis=nullptr)
Definition phase.h:334
const Def * rewrite_imm(const Def *def) final
const Def * rewrite_imm_App(const App *) final