MimIR
MimIR is my Intermediate Representation
Loading...
Searching...
No Matches
mem.h
Go to the documentation of this file.
1#pragma once
2
3#include <mim/axm.h>
4#include <mim/lam.h>
5#include <mim/world.h>
6
8
10
11namespace mim::plug::mem {
12
13/// @name mem.M
14///@{
15
16inline Lam* mut_con(World& w, nat_t a = 0) { return w.mut_con(w.call<M>(a)); } ///< Yields `con[mem.M 0]`.
17
18/// Yields `con[mem.M 0, dom]`.
19inline Lam* mut_con(const Def* dom) {
20 World& w = dom->world();
21 return w.mut_con({w.call<M>(0), dom});
22}
23
24/// If @p def is a `mem.M`-typed value, yields its memory type `mem.M a`; otherwise `nullptr`.
25inline const App* isa_mem(const Def* def) { return Axm::isa<mem::M>(def->type()); }
26
27/// Does @p pi already thread memory - a leading `mem.M`, either directly or grouped as the first
28/// component of the first parameter (e.g. the `Fn [mem.M 0, To, ins] → …` shape of a mem-threaded combiner)?
29inline bool has_leading_mem(const Pi* pi) {
30 if (pi->num_doms() == 0) return false;
31 auto dom0 = pi->dom(pi->num_doms(), 0);
32 if (Axm::isa<mem::M>(dom0)) return true;
33 if (auto sig = dom0->isa<Sigma>(); sig && sig->num_ops() != 0 && Axm::isa<mem::M>(sig->op(0))) return true;
34 return false;
35}
36
37/// Returns the (first) element of type `mem.M a` from the given tuple.
38inline const Def* mem_def(const Def* def) {
39 if (isa_mem(def)) return def;
40 if (def->isa<Arr>() || def->type()->isa<Arr>()) return {}; // don't look into possibly gigantic arrays
41
42 if (def->num_projs() > 1) {
43 for (auto proj : def->projs())
44 if (auto mem = mem_def(proj)) return mem;
45 }
46
47 return {};
48}
49
50/// Returns the memory argument of a function if it has one.
51inline const Def* mem_var(Lam* lam) { return mem_def(lam->var()); }
52
53/// Is @p type `mem.M` or a Sigma with a `mem.M` component?
54inline bool has_mem_ty(const Def* type) {
55 if (Axm::isa<mem::M>(type)) return true;
56 if (auto sigma = type->isa<Sigma>())
57 return std::ranges::any_of(sigma->ops(), [](const Def* op) { return Axm::isa<mem::M>(op); });
58 return false;
59}
60
61/// Removes recusively all occurences of mem from a type (sigma).
62inline const Def* strip_mem_ty(const Def* def) {
63 auto& world = def->world();
64
65 if (auto sigma = def->isa<Sigma>()) {
66 DefVec new_ops;
67 for (auto op : sigma->ops())
68 if (auto new_op = strip_mem_ty(op); new_op != world.sigma()) new_ops.push_back(new_op);
69
70 return world.sigma(new_ops);
71 } else if (Axm::isa<mem::M>(def)) {
72 return world.sigma();
73 }
74
75 return def;
76}
77///@}
78
79/// @name mem.Ptr
80///@{
81inline const Def* pointee(const Def* ptr) {
82 auto [pointee, _] = Axm::as<Ptr>(ptr->type())->args<2>();
83 return pointee;
84}
85///@}
86
87/// @name mem.lea
88///@{
89inline const Def* op_lea(const Def* ptr, const Def* index) {
90 World& w = ptr->world();
91 auto [pointee, addr_space] = Axm::as<Ptr>(ptr->type())->args<2>();
92 auto Ts = tuple_of_types(pointee);
93 return w.app(w.app(w.annex<lea>(), {pointee->arity(), Ts, addr_space}), {ptr, index});
94}
95
96/// Successively offsets @p ptr by each component of the index @p tuple, peeling one array dimension per `mem.lea`.
97inline const Def* op_lea_tuple(const Def* ptr, const Def* tuple) {
98 auto n = tuple->num_projs();
99 auto element = ptr;
100 for (size_t i = 0; i != n; ++i)
101 element = op_lea(element, tuple->proj(n, i));
102 return element;
103}
104///@}
105
106/// @name mem.alloc
107///@{
108inline const Def* op_alloc(const Def* type, const Def* as, const Def* mem) {
109 World& w = type->world();
110 return w.app(w.app(w.annex<alloc>(), {type, as}), mem);
111}
112inline const Def* op_alloc(const Def* type, const Def* mem) { return op_alloc(type, type->world().lit_nat_0(), mem); }
113///@}
114
115/// @name mem.slot
116///@{
117/// Builds the continuation-based `mem.slot (type, as)` applied to @p mem and the continuation @p ret.
118/// @p ret is a `Cn [mem.M as, mem.Ptr (type, as)]` receiving the fresh slot; its scope delimits the slot's lifetime.
119inline const Def* op_slot(const Def* type, const Def* as, const Def* mem, const Def* ret) {
120 World& w = type->world();
121 return w.app(w.app(w.annex<slot>(), {type, as}), {mem, ret});
122}
123/// Decomposes the continuation-based @p slot into `(mem, ret_lam, ret_mem, ptr)`,
124/// where `ret_mem` is the continuation's mem and `ptr` is the continuation's slot var;
125/// the slot's lifetime is `ret_lam`'s scope.
126/// All but `mem` are `nullptr` if the continuation is no mutable Lam.
127inline std::tuple<const Def*, Lam*, const Def*, const Def*> split_slot(const App* slot) {
128 auto [mem, ret] = slot->args<2>();
129 if (auto ret_lam = ret->isa_mut<Lam>()) return {mem, ret_lam, ret_lam->var(2, 0), ret_lam->var(2, 1)};
130 return {mem, nullptr, nullptr, nullptr};
131}
132
133///@}
134
135/// @name mem.malloc
136///@{
137inline const Def* op_malloc(const Def* type, const Def* as, const Def* mem) {
138 World& w = type->world();
139 auto size = w.call(core::trait::size, type);
140 return w.app(w.app(w.annex<malloc>(), {type, as}), {mem, size});
141}
142///@}
143
144/// @name mem.mslot
145///@{
146/// Builds the continuation-based `mem.mslot (type, as)` applied to `(mem, size)` and the continuation @p ret.
147/// @p ret is a `Cn [mem.M as, mem.Ptr (type, as)]` receiving the fresh slot; its scope delimits the slot's lifetime.
148inline const Def* op_mslot(const Def* type, const Def* as, const Def* mem, const Def* ret) {
149 World& w = type->world();
150 auto size = w.call(core::trait::size, type);
151 return w.app(w.app(w.annex<mslot>(), {type, as}), {w.tuple({mem, size}), ret});
152}
153///@}
154
155} // namespace mim::plug::mem
A (possibly paramterized) Array.
Definition tuple.h:305
static auto isa(const Def *def)
Definition axm.h:112
static auto as(const Def *def)
Definition axm.h:134
Base class for all Defs.
Definition def.h:289
World & world() const noexcept
Definition def.h:1105
const Def * var(nat_t a, nat_t i) noexcept
Definition def.h:492
auto projs(Projector auto f) const
Splits this Def via Def::projections into an Array (if A == std::dynamic_extent) or std::array (other...
Definition def.h:457
const Def * type() const noexcept
Yields the "raw" type of this Def (maybe nullptr).
Definition def.h:1119
nat_t num_projs() const
Yields Def::arity(), if it is a Lit, or 1 otherwise.
Definition def.h:1140
constexpr size_t num_ops() const noexcept
Definition def.h:378
A function.
Definition lam.h:91
A dependent function type.
Definition lam.h:14
const Def * dom() const
Definition lam.h:38
nat_t num_doms() const noexcept
Definition lam.h:40
A dependent tuple type.
Definition tuple.h:39
The World represents the whole program and manages creation of MimIR nodes (Defs).
Definition world.h:43
The mem Plugin
bool has_leading_mem(const Pi *pi)
Does pi already thread memory - a leading mem.M, either directly or grouped as the first component of...
Definition mem.h:29
const Def * mem_var(Lam *lam)
Returns the memory argument of a function if it has one.
Definition mem.h:51
const Def * mem_def(const Def *def)
Returns the (first) element of type mem.M a from the given tuple.
Definition mem.h:38
const Def * strip_mem_ty(const Def *def)
Removes recusively all occurences of mem from a type (sigma).
Definition mem.h:62
const Def * op_lea(const Def *ptr, const Def *index)
Definition mem.h:89
const Def * op_mslot(const Def *type, const Def *as, const Def *mem, const Def *ret)
Definition mem.h:148
Lam * mut_con(World &w, nat_t a=0)
Yields con[mem.M 0].
Definition mem.h:16
bool has_mem_ty(const Def *type)
Is type mem.M or a Sigma with a mem.M component?
Definition mem.h:54
const Def * op_alloc(const Def *type, const Def *as, const Def *mem)
Definition mem.h:108
const App * isa_mem(const Def *def)
If def is a mem.M-typed value, yields its memory type mem.M a; otherwise nullptr.
Definition mem.h:25
plug::core::M M
Definition autogen.h:14
std::tuple< const Def *, Lam *, const Def *, const Def * > split_slot(const App *slot)
Decomposes the continuation-based slot into (mem, ret_lam, ret_mem, ptr), where ret_mem is the contin...
Definition mem.h:127
const Def * pointee(const Def *ptr)
Definition mem.h:81
const Def * op_lea_tuple(const Def *ptr, const Def *tuple)
Successively offsets ptr by each component of the index tuple, peeling one array dimension per mem....
Definition mem.h:97
const Def * op_slot(const Def *type, const Def *as, const Def *mem, const Def *ret)
Definition mem.h:119
const Def * op_malloc(const Def *type, const Def *as, const Def *mem)
Definition mem.h:137
The tuple Plugin
u64 nat_t
Definition types.h:37
const Def * tuple_of_types(const Def *t)
Definition tuple.cpp:167
fe::Vector< const Def * > DefVec
Definition def.h:98