MimIR 0.1
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/phase.h"
6
8#include "mim/plug/mem/mem.h"
9
10namespace mim::plug::clos {
11
12/// This pass lowers *typed closures* to *untyped closures*.
13/// For details on typed closures, see ClosConv.
14/// In general, untyped closure have the form `(pointer-to-environment, code)` with the following exceptions:
15/// * Lam%s in callee-position should be λ-lifted and thus don't receive an environment.
16/// * External and imported (not set) Lam%s also don't receive an environment.
17/// They are appropriately η-wrapped by ClosConv.
18/// * If the environment is of integer type, it's directly stored in the environment-pointer ("unboxed").
19/// @note In theory this should work for other primitive types as well, but the LL backend does not handle the
20/// required conversion correctly.
21///
22/// Further, first class continuations are rewritten to returning functions.
23/// They receive `⊥` as a dummy continuation.
24/// Therefore Clos2SJLJ should have taken place prior to this pass.
25///
26/// This pass will heap-allocate ClosKind::esc closures and stack-allocate everything else.
27/// These annotations are introduced by LowerTypedClosPrep.
28class LowerTypedClos : public Phase {
29public:
31 : Phase(world, "lower_typed_clos", true) {}
32
33 void start() override;
34
35private:
36 using StubQueue = std::queue<std::tuple<const Def*, const Def*, Lam*>>;
37
38 /// Recursively rewrites a Def.
39 const Def* rewrite(const Def* def);
40
41 /// Describes how the environment should be treated.
42 enum Mode {
43 Box = 0, //< Environment is boxed (default).
44 Unbox, //< Environments is of primitive type (currently `iN`s) and directly stored in the pointer.
45 No_Env //< Lambda has no environment (lifted, top-level).
46 };
47
48 /// Create a new Lam stub.
49 /// @p adjust_bb_type is true if the @p lam should be rewritten to a returning function.
50 Lam* make_stub(Lam* lam, enum Mode mode, bool adjust_bb_type);
51
52 /// @name Helpers
53 ///@{
54 /// wrapper arround old2new_
55 const Def* map(const Def* old_def, const Def* new_def) { return old2new_[old_def] = new_def; }
56 Def* map(const Def* old_def, Def* new_def) {
57 old2new_[old_def] = new_def;
58 return new_def;
59 }
60
61 /// Pointer type used to represent environments
62 const Def* env_type() {
63 auto& w = world();
64 return w.call<mem::Ptr0>(w.sigma());
65 }
66 ///@}
67
68 Def2Def old2new_;
69 StubQueue worklist_;
70
71 const Def* dummy_ret_ = nullptr; //< dummy return continuation
72
73 /// @name memory-tokens
74 ///@{
75 const Def* lvm_; //< Last visited memory token
76 const Def* lcm_; //< Last created memory token
77 ///@}
78
79 std::vector<Lam*> new_externals_;
80};
81
82} // namespace mim::plug::clos
Base class for all Defs.
Definition def.h:220
A function.
Definition lam.h:96
As opposed to a Pass, a Phase does one thing at a time and does not mix with other Phases.
Definition phase.h:15
World & world()
Definition phase.h:25
The World represents the whole program and manages creation of MimIR nodes (Defs).
Definition world.h:33
This pass lowers typed closures to untyped closures.
void start() override
Actual entry.
The clos Plugin
Definition clos.h:7
DefMap< const Def * > Def2Def
Definition def.h:59