MimIR 0.1
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/axiom.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) { return w.mut_con(w.annex<M>()); } ///< Yields `con[%mem.M]`.
17
18/// Yields `con[%mem.M, dom]`.
19inline Lam* mut_con(const Def* dom) {
20 World& w = dom->world();
21 return w.mut_con({w.annex<M>(), dom});
22}
23
24/// Returns the (first) element of type mem::M from the given tuple.
25inline const Def* mem_def(const Def* def) {
26 if (match<mem::M>(def->type())) return def;
27 if (def->type()->isa<Arr>()) return {}; // don't look into possibly gigantic arrays
28
29 if (def->num_projs() > 1) {
30 for (auto proj : def->projs())
31 if (auto mem = mem_def(proj)) return mem;
32 }
33
34 return {};
35}
36
37/// Returns the memory argument of a function if it has one.
38inline const Def* mem_var(Lam* lam) { return mem_def(lam->var()); }
39
40/// Swaps the memory occurrences in the given def with the given memory.
41inline const Def* replace_mem(const Def* mem, const Def* arg) {
42 // TODO: maybe use rebuild instead?
43 if (arg->num_projs() > 1) {
44 auto& w = mem->world();
45 return w.tuple(DefVec(arg->num_projs(), [&](auto i) { return replace_mem(mem, arg->proj(i)); }));
46 }
47
48 if (match<mem::M>(arg->type())) return mem;
49
50 return arg;
51}
52
53/// Removes recusively all occurences of mem from a type (sigma).
54inline const Def* strip_mem_ty(const Def* def) {
55 auto& world = def->world();
56
57 if (auto sigma = def->isa<Sigma>()) {
58 DefVec new_ops;
59 for (auto op : sigma->ops())
60 if (auto new_op = strip_mem_ty(op); new_op != world.sigma()) new_ops.push_back(new_op);
61
62 return world.sigma(new_ops);
63 } else if (match<mem::M>(def)) {
64 return world.sigma();
65 }
66
67 return def;
68}
69
70/// Recursively removes all occurrences of mem from a tuple.
71/// Returns an empty tuple if applied with mem alone.
72inline const Def* strip_mem(const Def* def) {
73 auto& world = def->world();
74
75 if (auto tuple = def->isa<Tuple>()) {
76 DefVec new_ops;
77 for (auto op : tuple->ops())
78 if (auto new_op = strip_mem(op); new_op != world.tuple()) new_ops.push_back(new_op);
79
80 return world.tuple(new_ops);
81 } else if (match<mem::M>(def->type())) {
82 return world.tuple();
83 } else if (auto extract = def->isa<Extract>()) {
84 // The case that this one element is a mem and should return () is handled above.
85 if (extract->num_projs() == 1) return extract;
86
87 DefVec new_ops;
88 for (auto op : extract->projs())
89 if (auto new_op = strip_mem(op); new_op != world.tuple()) new_ops.push_back(new_op);
90
91 return world.tuple(new_ops);
92 }
93
94 return def;
95}
96///@}
97
98/// @name %%mem.Ptr
99///@{
100enum class AddrSpace : nat_t {
106};
107///@}
108
109/// @name %%mem.lea
110///@{
111inline const Def* op_lea(const Def* ptr, const Def* index) {
112 World& w = ptr->world();
113 auto [pointee, addr_space] = force<Ptr>(ptr->type())->args<2>();
114 auto Ts = tuple_of_types(pointee);
115 return w.app(w.app(w.annex<lea>(), {pointee->arity(), Ts, addr_space}), {ptr, index});
116}
117
118inline const Def* op_lea_unsafe(const Def* ptr, const Def* i) {
119 World& w = ptr->world();
120 return op_lea(ptr, w.call(core::conv::u, force<Ptr>(ptr->type())->arg(0)->arity(), i));
121}
122
123inline const Def* op_lea_unsafe(const Def* ptr, u64 i) { return op_lea_unsafe(ptr, ptr->world().lit_i64(i)); }
124///@}
125
126/// @name %%mem.remem
127///@{
128inline const Def* op_remem(const Def* mem) {
129 World& w = mem->world();
130 return w.app(w.annex<remem>(), mem);
131}
132///@}
133
134/// @name %%mem.alloc
135///@{
136inline const Def* op_alloc(const Def* type, const Def* mem) {
137 World& w = type->world();
138 return w.app(w.app(w.annex<alloc>(), {type, w.lit_nat_0()}), mem);
139}
140///@}
141
142/// @name %%mem.slot
143///@{
144inline const Def* op_slot(const Def* type, const Def* mem) {
145 World& w = type->world();
146 return w.app(w.app(w.annex<slot>(), {type, w.lit_nat_0()}), {mem, w.lit_nat(w.curr_gid())});
147}
148///@}
149
150/// @name %%mem.malloc
151///@{
152inline const Def* op_malloc(const Def* type, const Def* mem) {
153 World& w = type->world();
154 auto size = w.call(core::trait::size, type);
155 return w.app(w.app(w.annex<malloc>(), {type, w.lit_nat_0()}), {mem, size});
156}
157///@}
158
159/// @name %%mem.mslot
160///@{
161inline const Def* op_mslot(const Def* type, const Def* mem, const Def* id) {
162 World& w = type->world();
163 auto size = w.call(core::trait::size, type);
164 return w.app(w.app(w.annex<mslot>(), {type, w.lit_nat_0()}), {mem, size, id});
165}
166///@}
167
168} // namespace mim::plug::mem
A (possibly paramterized) Array.
Definition tuple.h:68
Base class for all Defs.
Definition def.h:198
World & world() const noexcept
Definition def.cpp:413
constexpr auto ops() const noexcept
Definition def.h:261
const Def * var(nat_t a, nat_t i) noexcept
Definition def.h:379
auto projs(F f) const
Splits this Def via Def::projections into an Array (if A == std::dynamic_extent) or std::array (other...
Definition def.h:345
const Def * type() const noexcept
Yields the "raw" type of this Def (maybe nullptr).
Definition def.h:242
nat_t num_projs() const
Yields Def::as_lit_arity(), if it is in fact a Lit, or 1 otherwise.
Definition def.h:335
Extracts from a Sigma or Array-typed Extract::tuple the element at position Extract::index.
Definition tuple.h:155
A function.
Definition lam.h:105
A dependent tuple type.
Definition tuple.h:9
Data constructor for a Sigma.
Definition tuple.h:50
The World represents the whole program and manages creation of MimIR nodes (Defs).
Definition world.h:33
const Lit * lit_i64()
Definition world.h:394
The mem Plugin
Definition mem.h:11
const Def * op_slot(const Def *type, const Def *mem)
Definition mem.h:144
const Def * mem_var(Lam *lam)
Returns the memory argument of a function if it has one.
Definition mem.h:38
const Def * replace_mem(const Def *mem, const Def *arg)
Swaps the memory occurrences in the given def with the given memory.
Definition mem.h:41
const Def * mem_def(const Def *def)
Returns the (first) element of type mem::M from the given tuple.
Definition mem.h:25
const Def * op_mslot(const Def *type, const Def *mem, const Def *id)
Definition mem.h:161
const Def * op_malloc(const Def *type, const Def *mem)
Definition mem.h:152
const Def * strip_mem_ty(const Def *def)
Removes recusively all occurences of mem from a type (sigma).
Definition mem.h:54
const Def * op_lea(const Def *ptr, const Def *index)
Definition mem.h:111
const Def * op_alloc(const Def *type, const Def *mem)
Definition mem.h:136
const Def * op_lea_unsafe(const Def *ptr, const Def *i)
Definition mem.h:118
Lam * mut_con(World &w)
Yields con[mem.M].
Definition mem.h:16
const Def * strip_mem(const Def *def)
Recursively removes all occurrences of mem from a tuple.
Definition mem.h:72
const Def * op_remem(const Def *mem)
Definition mem.h:128
u64 nat_t
Definition types.h:43
Vector< const Def * > DefVec
Definition def.h:50
const Def * tuple_of_types(const Def *t)
Definition tuple.cpp:109
auto match(const Def *def)
Definition axiom.h:112
uint64_t u64
Definition types.h:34
auto force(const Def *def)
Definition axiom.h:133