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/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/// Returns the (first) element of type `%mem.M a` from the given tuple.
25inline const Def* mem_def(const Def* def) {
26 if (Axm::isa<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/// Removes recusively all occurences of mem from a type (sigma).
41inline const Def* strip_mem_ty(const Def* def) {
42 auto& world = def->world();
43
44 if (auto sigma = def->isa<Sigma>()) {
45 DefVec new_ops;
46 for (auto op : sigma->ops())
47 if (auto new_op = strip_mem_ty(op); new_op != world.sigma()) new_ops.push_back(new_op);
48
49 return world.sigma(new_ops);
50 } else if (Axm::isa<mem::M>(def)) {
51 return world.sigma();
52 }
53
54 return def;
55}
56
57/// Recursively removes all occurrences of mem from a tuple.
58/// Returns an empty tuple if applied with mem alone.
59inline const Def* strip_mem(const Def* def) {
60 auto& world = def->world();
61
62 if (auto tuple = def->isa<Tuple>()) {
63 DefVec new_ops;
64 for (auto op : tuple->ops())
65 if (auto new_op = strip_mem(op); new_op != world.tuple()) new_ops.push_back(new_op);
66
67 return world.tuple(new_ops);
68 } else if (Axm::isa<mem::M>(def->type())) {
69 return world.tuple();
70 } else if (auto extract = def->isa<Extract>()) {
71 // The case that this one element is a mem and should return () is handled above.
72 if (extract->num_projs() == 1) return extract;
73
74 DefVec new_ops;
75 for (auto op : extract->projs())
76 if (auto new_op = strip_mem(op); new_op != world.tuple()) new_ops.push_back(new_op);
77
78 return world.tuple(new_ops);
79 }
80
81 return def;
82}
83///@}
84
85/// @name %%mem.lea
86///@{
87inline const Def* op_lea(const Def* ptr, const Def* index) {
88 World& w = ptr->world();
89 auto [pointee, addr_space] = Axm::as<Ptr>(ptr->type())->args<2>();
90 auto Ts = tuple_of_types(pointee);
91 return w.app(w.app(w.annex<lea>(), {pointee->arity(), Ts, addr_space}), {ptr, index});
92}
93
94inline const Def* op_lea_unsafe(const Def* ptr, const Def* i) {
95 World& w = ptr->world();
96 return op_lea(ptr, w.call(core::conv::u, Axm::as<Ptr>(ptr->type())->arg(0)->arity(), i));
97}
98
99inline const Def* op_lea_unsafe(const Def* ptr, u64 i) { return op_lea_unsafe(ptr, ptr->world().lit_i64(i)); }
100///@}
101
102/// @name %%mem.alloc
103///@{
104inline const Def* op_alloc(const Def* type, const Def* as, const Def* mem) {
105 World& w = type->world();
106 return w.app(w.app(w.annex<alloc>(), {type, as}), mem);
107}
108inline const Def* op_alloc(const Def* type, const Def* mem) { return op_alloc(type, type->world().lit_nat_0(), mem); }
109///@}
110
111/// @name %%mem.slot
112///@{
113inline const Def* op_slot(const Def* type, const Def* as, const Def* mem) {
114 World& w = type->world();
115 return w.app(w.app(w.annex<slot>(), {type, as}), {mem, w.lit_nat(w.curr_gid())});
116}
117inline const Def* op_slot(const Def* type, const Def* mem) { return op_slot(type, type->world().lit_nat_0(), mem); }
118///@}
119
120/// @name %%mem.malloc
121///@{
122inline const Def* op_malloc(const Def* type, const Def* as, const Def* mem) {
123 World& w = type->world();
124 auto size = w.call(core::trait::size, type);
125 return w.app(w.app(w.annex<malloc>(), {type, as}), {mem, size});
126}
127inline const Def* op_malloc(const Def* type, const Def* mem) { return op_malloc(type, type->world().lit_nat_0(), mem); }
128///@}
129
130/// @name %%mem.mslot
131///@{
132inline const Def* op_mslot(const Def* type, const Def* as, const Def* mem, const Def* id) {
133 World& w = type->world();
134 auto size = w.call(core::trait::size, type);
135 return w.app(w.app(w.annex<mslot>(), {type, as}), {mem, size, id});
136}
137inline const Def* op_mslot(const Def* type, const Def* mem, const Def* id) {
138 return op_mslot(type, type->world().lit_nat_0(), mem, id);
139}
140///@}
141
142} // namespace mim::plug::mem
A (possibly paramterized) Array.
Definition tuple.h:117
static auto isa(const Def *def)
Definition axm.h:107
static auto as(const Def *def)
Definition axm.h:129
Base class for all Defs.
Definition def.h:251
World & world() const noexcept
Definition def.cpp:438
constexpr auto ops() const noexcept
Definition def.h:305
const Def * var(nat_t a, nat_t i) noexcept
Definition def.h:429
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:390
const Def * type() const noexcept
Yields the "raw" type of this Def (maybe nullptr).
Definition def.cpp:446
nat_t num_projs() const
Yields Def::arity(), if it is a Lit, or 1 otherwise.
Definition def.cpp:580
Extracts from a Sigma or Array-typed Extract::tuple the element at position Extract::index.
Definition tuple.h:206
A function.
Definition lam.h:110
A dependent tuple type.
Definition tuple.h:20
Data constructor for a Sigma.
Definition tuple.h:68
The World represents the whole program and manages creation of MimIR nodes (Defs).
Definition world.h:31
const Lit * lit_i64()
Definition world.h:464
The mem Plugin
Definition mem.h:11
const Def * op_slot(const Def *type, const Def *as, const Def *mem)
Definition mem.h:113
const Def * mem_var(Lam *lam)
Returns the memory argument of a function if it has one.
Definition mem.h:38
const Def * mem_def(const Def *def)
Returns the (first) element of type mem.M a from the given tuple.
Definition mem.h:25
const Def * strip_mem_ty(const Def *def)
Removes recusively all occurences of mem from a type (sigma).
Definition mem.h:41
const Def * op_lea(const Def *ptr, const Def *index)
Definition mem.h:87
const Def * op_lea_unsafe(const Def *ptr, const Def *i)
Definition mem.h:94
Lam * mut_con(World &w, nat_t a=0)
Yields con[mem.M 0].
Definition mem.h:16
const Def * strip_mem(const Def *def)
Recursively removes all occurrences of mem from a tuple.
Definition mem.h:59
const Def * op_mslot(const Def *type, const Def *as, const Def *mem, const Def *id)
Definition mem.h:132
const Def * op_alloc(const Def *type, const Def *as, const Def *mem)
Definition mem.h:104
const Def * op_malloc(const Def *type, const Def *as, const Def *mem)
Definition mem.h:122
The tuple Plugin
u64 nat_t
Definition types.h:44
Vector< const Def * > DefVec
Definition def.h:77
const Def * tuple_of_types(const Def *t)
Definition tuple.cpp:162
uint64_t u64
Definition types.h:35