MimIR 0.1
MimIR is my Intermediate Representation
Loading...
Searching...
No Matches
emitter.h
Go to the documentation of this file.
1#pragma once
2
4#include "mim/phase/phase.h"
5#include "mim/world.h"
6
7namespace mim {
8
9template<class Value, class Type, class BB, class Child> class Emitter : public ScopePhase {
10private:
11 constexpr const Child& child() const { return *static_cast<const Child*>(this); }
12 constexpr Child& child() { return *static_cast<Child*>(this); }
13
14 /// Internal wrapper for Emitter::emit that schedules @p def and invokes `child().emit_bb`.
15 Value emit_(const Def* def) {
16 auto place = scheduler_.smart(def);
17 auto& bb = lam2bb_[place->as_mut<Lam>()];
18 return child().emit_bb(bb, def);
19 }
20
21public:
23
24protected:
25 Emitter(World& world, std::string_view name, std::ostream& ostream)
26 : ScopePhase(world, name, false)
27 , ostream_(ostream) {}
28
29 std::ostream& ostream() const { return ostream_; }
30
31 /// Recursively emits code.
32 /// `mem`-typed @p def%s return sth that is `!child().is_valid(value)`.
33 /// This variant asserts in this case.
34 Value emit(const Def* def) {
35 auto res = emit_unsafe(def);
36 assert(child().is_valid(res));
37 return res;
38 }
39
40 /// As above but returning `!child().is_valid(value)` is permitted.
41 Value emit_unsafe(const Def* def) {
42 if (auto i = globals_.find(def); i != globals_.end()) return i->second;
43 if (auto i = locals_.find(def); i != locals_.end()) return i->second;
44
45 auto val = emit_(def);
46 return locals_[def] = val;
47 }
48
49 void visit(const Scope& scope) override {
50 if (entry_ = scope.entry()->isa_mut<Lam>(); !entry_) return;
51
52 if (!entry_->is_set()) {
53 child().emit_imported(entry_);
54 return;
55 }
56
57 auto muts = Scheduler::schedule(scope); // TODO make sure to not compute twice
58
59 // make sure that we don't need to rehash later on
60 for (auto mut : muts)
61 if (auto lam = mut->isa<Lam>()) lam2bb_.emplace(lam, BB());
62 auto old_size = lam2bb_.size();
63
64 entry_ = scope.entry()->as_mut<Lam>();
65 assert(entry_->ret_var());
66
67 auto fct = child().prepare(scope);
68
69 Scheduler new_scheduler(scope);
70 swap(scheduler_, new_scheduler);
71
72 for (auto mut : muts) {
73 if (auto lam = mut->isa<Lam>(); lam && lam != scope.exit()) {
74 assert(lam == entry_ || Lam::isa_basicblock(lam));
75 child().emit_epilogue(lam);
76 }
77 }
78
79 child().finalize(scope);
80 locals_.clear();
81 assert_unused(lam2bb_.size() == old_size && "really make sure we didn't triger a rehash");
82 }
83
84 std::ostream& ostream_;
90 Lam* entry_ = nullptr;
91};
92
93} // namespace mim
Base class for all Defs.
Definition def.h:220
bool is_set() const
Yields true if empty or the last op is set.
Definition def.cpp:311
T * as_mut() const
Asserts that this is a mutable, casts constness away and performs a static_cast to T.
Definition def.h:452
T * isa_mut() const
If this is *mut*able, it will cast constness away and perform a dynamic_cast to T.
Definition def.h:444
DefMap< Value > locals_
Definition emitter.h:86
Value emit(const Def *def)
Recursively emits code.
Definition emitter.h:34
void visit(const Scope &scope) override
Definition emitter.h:49
std::ostream & ostream() const
Definition emitter.h:29
Scheduler scheduler_
Definition emitter.h:85
Value emit_unsafe(const Def *def)
As above but returning !child().is_valid(value) is permitted.
Definition emitter.h:41
DefMap< Value > globals_
Definition emitter.h:87
DefMap< Type > types_
Definition emitter.h:88
Emitter(World &world, std::string_view name, std::ostream &ostream)
Definition emitter.h:25
LamMap< BB > lam2bb_
Definition emitter.h:89
std::ostream & ostream_
Definition emitter.h:84
Lam * entry_
Definition emitter.h:90
A function.
Definition lam.h:96
static const Lam * isa_basicblock(Ref d)
Definition lam.h:132
Ref ret_var()
Yields the Lam::var of the Lam::ret_pi.
Definition lam.h:146
std::string_view name() const
Definition phase.h:26
World & world()
Definition phase.h:25
Def * smart(const Def *)
Definition schedule.cpp:84
static Schedule schedule(const Scope &)
Definition schedule.cpp:112
Transitively visits all reachable Scopes in World that do not have free variables.
Definition phase.h:149
const Scope & scope() const
Definition phase.h:159
A Scope represents a region of Defs that are live from the view of an entry's Var.
Definition scope.h:21
Def * entry() const
Definition scope.h:32
Def * exit() const
Definition scope.h:33
Keeps track of indentation level.
Definition print.h:195
The World represents the whole program and manages creation of MimIR nodes (Defs).
Definition world.h:33
Definition cfg.h:11
GIDMap< const Def *, To > DefMap
Definition def.h:57
GIDMap< Lam *, To > LamMap
Definition lam.h:188