MimIR
0.4-dev
MimIR is my Intermediate Representation
Toggle main menu visibility
Loading...
Searching...
No Matches
emitter.h
Go to the documentation of this file.
1
#pragma once
2
3
#include "
mim/def.h
"
4
#include "
mim/phase.h
"
5
#include "
mim/schedule.h
"
6
#include "
mim/world.h
"
7
8
namespace
mim
{
9
10
template
<
class
Value,
class
Type,
class
BB,
class
Child>
11
class
Emitter
:
public
NestPhase
<Lam> {
12
private
:
13
constexpr
const
Child& child()
const
{
return
*
static_cast<
const
Child*
>
(
this
); }
14
constexpr
Child& child() {
return
*
static_cast<
Child*
>
(
this
); }
15
16
/// Internal wrapper for Emitter::emit that schedules @p def and invokes `child().emit_bb`.
17
Value emit_(
const
Def
* def) {
18
auto
place =
scheduler_
.
smart
(
curr_lam_
, def);
19
auto
& bb =
lam2bb_
[place->mut()->template as<Lam>()];
20
return
child().emit_bb(bb, def);
21
}
22
23
public
:
24
fe::Tab
tab
= fe::Tab::spaces();
25
26
protected
:
27
Emitter
(
World
&
world
, std::string
name
, std::ostream&
ostream
,
bool
schedule
=
false
)
28
:
NestPhase
<
Lam
>(
world
, std::move(
name
), false,
schedule
)
29
,
ostream_
(
ostream
) {}
30
31
virtual
bool
direct_style
() {
return
false
; }
32
33
std::ostream&
ostream
()
const
{
return
ostream_
; }
34
35
/// Recursively emits code.
36
/// `mem`-typed @p def%s return sth that is `!child().is_valid(value)`.
37
/// This variant asserts in this case.
38
Value
emit
(
const
Def
* def) {
39
auto
res =
emit_unsafe
(def);
40
assert(child().is_valid(res));
41
return
res;
42
}
43
44
/// As above but returning `!child().is_valid(value)` is permitted.
45
Value
emit_unsafe
(
const
Def
* def) {
46
if
(
auto
i =
globals_
.find(def); i !=
globals_
.end())
return
i->second;
47
if
(
auto
i =
locals_
.find(def); i !=
locals_
.end())
return
i->second;
48
49
auto
val = emit_(def);
50
return
locals_
[def] = val;
51
}
52
53
void
visit
(
const
Nest
&
nest
)
override
{
54
if
(!
root
()->is_set()) {
55
child().emit_imported(
root
());
56
return
;
57
}
58
59
schedule_
=
Scheduler::schedule
(
nest
);
// cached; Child::finalize needs the very same schedule
60
const
auto
& muts =
schedule_
;
61
62
// make sure that we don't need to rehash later on
63
for
(
auto
mut : muts)
64
if
(
auto
lam = mut->isa<
Lam
>())
lam2bb_
.try_emplace(lam, BB());
65
auto
old_size =
lam2bb_
.size();
66
67
if
(!child().
direct_style
()) assert(
root
()->ret_var());
68
69
auto
fct = child().prepare();
70
71
Scheduler
new_scheduler(
nest
);
72
swap(
scheduler_
, new_scheduler);
73
74
for
(
auto
mut : muts) {
75
if
(
auto
lam = mut->isa<
Lam
>()) {
76
curr_lam_
= lam;
77
if
(!child().
direct_style
()) assert(lam ==
root
() ||
Lam::isa_basicblock
(lam));
78
child().emit_epilogue(lam);
79
}
80
}
81
82
child().finalize();
83
locals_
.clear();
84
assert_unused(
lam2bb_
.size() == old_size &&
"really make sure we didn't trigger a rehash"
);
85
// A BB never crosses a function boundary: Nest::contains is `def->has_free_vars_in(vars())`,
86
// so a *closed* Lam is never a member of another Lam's Nest - and it cannot belong to two Nests either,
87
// since a Lam free in the vars of two closed Lams would make the outer one open.
88
// Every `BB&` handed out by emit_ died with the calls above, so clearing here is safe.
89
// Without it, Child::finalize re-walks the BBs of all previously emitted functions - O(n²) in program size.
90
lam2bb_
.clear();
91
}
92
93
/// The Scheduler::schedule of the function currently being emitted; see Emitter::visit.
94
const
Scheduler::Schedule
&
schedule
()
const
{
return
schedule_
; }
95
96
Lam
*
curr_lam_
=
nullptr
;
97
std::ostream&
ostream_
;
98
Scheduler
scheduler_
;
99
Scheduler::Schedule
schedule_
;
100
DefMap<Value>
locals_
;
101
DefMap<Value>
globals_
;
102
DefMap<Type>
types_
;
103
LamMap<BB>
lam2bb_
;
104
};
105
106
}
// namespace mim
mim::ClosedMutPhase< Lam >::root
Lam * root() const
Definition
phase.h:624
mim::Def
Base class for all Defs.
Definition
def.h:273
mim::Emitter< std::string, std::string, BB, Emitter >::locals_
DefMap< std::string > locals_
Definition
emitter.h:100
mim::Emitter< std::string, std::string, BB, Emitter >::schedule_
Scheduler::Schedule schedule_
Definition
emitter.h:99
mim::Emitter< std::string, std::string, BB, Emitter >::schedule
const Scheduler::Schedule & schedule() const
Definition
emitter.h:94
mim::Emitter::emit
Value emit(const Def *def)
Recursively emits code.
Definition
emitter.h:38
mim::Emitter::direct_style
virtual bool direct_style()
Definition
emitter.h:31
mim::Emitter< std::string, std::string, BB, Emitter >::tab
fe::Tab tab
Definition
emitter.h:24
mim::Emitter< std::string, std::string, BB, Emitter >::ostream
std::ostream & ostream() const
Definition
emitter.h:33
mim::Emitter::Emitter
Emitter(World &world, std::string name, std::ostream &ostream, bool schedule=false)
Definition
emitter.h:27
mim::Emitter::scheduler_
Scheduler scheduler_
Definition
emitter.h:98
mim::Emitter< std::string, std::string, BB, Emitter >::emit_unsafe
std::string emit_unsafe(const Def *def)
Definition
emitter.h:45
mim::Emitter< std::string, std::string, BB, Emitter >::globals_
DefMap< std::string > globals_
Definition
emitter.h:101
mim::Emitter::curr_lam_
Lam * curr_lam_
Definition
emitter.h:96
mim::Emitter< std::string, std::string, BB, Emitter >::types_
DefMap< std::string > types_
Definition
emitter.h:102
mim::Emitter::lam2bb_
LamMap< BB > lam2bb_
Definition
emitter.h:103
mim::Emitter::visit
void visit(const Nest &nest) override
Definition
emitter.h:53
mim::Emitter< std::string, std::string, BB, Emitter >::ostream_
std::ostream & ostream_
Definition
emitter.h:97
mim::Lam
A function.
Definition
lam.h:113
mim::Lam::isa_basicblock
static const Lam * isa_basicblock(const Def *d)
Definition
lam.h:145
mim::NestPhase< Lam >::nest
const Nest & nest() const
Definition
phase.h:642
mim::NestPhase< Lam >::NestPhase
NestPhase(World &world, std::string name, bool elide_empty, bool schedule=false)
Definition
phase.h:637
mim::Nest
Builds a nesting tree for all mutables/binders.
Definition
nest.h:31
mim::Phase::name
std::string_view name() const
Definition
phase.h:80
mim::Phase::world
World & world()
Definition
phase.h:77
mim::Scheduler
Definition
schedule.h:44
mim::Scheduler::smart
const Nest::Node * smart(Def *curr, const Def *)
Definition
schedule.cpp:75
mim::Scheduler::Schedule
fe::Vector< Def * > Schedule
Definition
schedule.h:79
mim::Scheduler::schedule
static Schedule schedule(const Nest &)
Definition
schedule.cpp:121
mim::World
The World represents the whole program and manages creation of MimIR nodes (Defs).
Definition
world.h:40
def.h
mim
Definition
ast.h:16
mim::DefMap
GIDMap< const Def *, To > DefMap
Definition
def.h:88
mim::LamMap
GIDMap< Lam *, To > LamMap
Definition
lam.h:219
phase.h
schedule.h
world.h
include
mim
be
emitter.h
Generated by
1.18.0