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